packages feed

dhall 1.24.0 → 1.42.3

raw patch · 3837 files changed

Files

CHANGELOG.md view
@@ -1,504 +1,1521 @@-1.24.0--* Supports version 8.0.0 of the standard-    * See: https://github.com/dhall-lang/dhall-lang/releases/tag/v8.0.0-* BREAKING CHANGE: Allow tabs and blank lines in multi-line strings-    * Blank lines are now ignored for the purpose of dedenting multiline strings-    * Lines with leading tabs (or mixed tabs and spaces) are now dedented, too,-      so long as they all share the same prefix-    * This is technically a breaking change, but unlikely to affect programs-      in practice, especially if they were formatted with `dhall format`.  This-      change mainly affects programs that were not indented correctly.-    * See the changelog for standard version 8.0.0 for more details-* BREAKING CHANGE: Simplify bare interpolations-    * Expressions like `λ(x : Text) → "${x}"` now simplify to `λ(x : Text) → x`-    * This is a technically breaking change because it changes how these sorts-      of expressions are serialized.  This does not affect semantic integrity-      checks and the new simplified expressions are extensionally equivalent to-      their older counterpart expressions.-    * See the changelog for standard version 8.0.0 for more details-* BREAKING CHANGE: Encode integrity check as multihash-    * Semantic integrity checks are now encoded using the multihash spec-    * This is a technically breaking change that does not perturb the hash for-      user-facing semantic integrity checks.  This only affects how expressions-      with unresolved imports are serialized, but semantic integrity checks are-      only computed for fully-resolved imports.-    * See the changelog for standard version 8.0.0 for more details-* BUG FIX: Fix type-checker to reject invalid record type annotations-    * e.g. `{ x = 1 } : { x : Text }` was not properly rejected by the type-      checker-    * See: https://github.com/dhall-lang/dhall-haskell/pull/965-* BUG FIX: Custom header forwarding fixed-    * Forwarding custom headers could previously fail in various ways, such as:-        * Cyclic imports leading to endless network requests-        * Resolving a non-existent import for the custom headers-        * Resolving an existing but incorrect import for the custom headers-    * This change fixes that by forwarding custom headers by value instead of-      by reference-    * See: https://github.com/dhall-lang/dhall-haskell/pull/967-* BUG FIX: Fix GHCJS support-    * `Natural/fold` was broken in version 1.22, which this change fixes-    * Specifically, it would hang for `Natural` numbers greater than 1-    * See: https://github.com/dhall-lang/dhall-haskell/pull/985-* BUG FIX: `dhall diff` no longer double-prints key-value separators-    * See: https://github.com/dhall-lang/dhall-haskell/pull/952-* Feature: Record projection by expression-    * You can now project out a subset of record fields by the expected type-    * `let t = { x : Natural } let p = { x = 1, y = 2 } in p.(t) = { x = 1 }`-    * See the changelog for standard version 8.0.0 for more details-* Feature: Inline headers-    * You no longer need to specify custom headers in a separate import.  You-      can now specify them inline within the same file.-    * e.g.: `https://example.com/x using [ { header = "Foo", value = "Bar" } ]`-    * See the changelog for standard version 8.0.0 for more details-* Feature: Allow `Sort` as a type annotation-    * An expression such as `Kind → Kind : Sort` will now type-check-    * `Sort` is still disallowed outside of a type annotation-    * See the changelog for standard version 8.0.0 for more details-* Feature: Allow self-describe-cbor when decoding-    * Dhall expressions serialized as CBOR can be tagged to describe themselves-      as CBOR without affecting decoding-    * See the changelog for standard version 8.0.0 for more details-* Feature: New `--file` option for `dhall` commands-    * In other words, instead of `dhall <<< './some/file` you can now use-      `dhall --file some/file`-    * See: https://github.com/dhall-lang/dhall-haskell/pull/949-* Feature: New `--cache` flag for `dhall freeze` command-    * This automates the idiom used by the Prelude to optimistically cache-      imports but gracefully degrade if the semantic integrity check fails-    * See: https://github.com/dhall-lang/dhall-haskell/pull/980-* Feature: Add `:clear` command to `dhall repl`-    * This deletes previous bindings from the history so that they can be-      garbage collected-    * See: https://github.com/dhall-lang/dhall-haskell/pull/966-* Feature: New `chunkExprs` `Traversal` added to `Dhall.Core`-    * See: https://github.com/dhall-lang/dhall-haskell/pull/954-* Feature: New `Dhall.Optics` module-    * This re-exports some convenient @lens@ utilities used internally for-      packages trying to avoid a @lens@ dependency-    * See: https://github.com/dhall-lang/dhall-haskell/pull/986-* More GHC 8.8 support-    * See: https://github.com/dhall-lang/dhall-haskell/pull/961--1.23.0--* BREAKING CHANGE: Fix marshaling union literals-    * 1.22.0 introduced two separate bugs in marshaling union literals between-      Dhall and Haskell, which this release fixes:-        * Dhall enums did not correctly map onto Haskell enums-        * New-style union literals (i.e. `< A : T >.A x`) were not correctly-          supported-    * See: https://github.com/dhall-lang/dhall-haskell/pull/918-    * See: https://github.com/dhall-lang/dhall-haskell/pull/927-    * See: https://github.com/dhall-lang/dhall-haskell/pull/936-* BUG FIX: Fix α-normalization-    * Version 1.22.0 introduced a new faster evaluation algorithm, but the new-      algorithm introduced two α-normalization regression, which this release-      fixes-    * The primary effect of this bug was that semantic integrity checks would-      fail for expressions that contain an `if`/`then`/else` expression in their-      normal form-    * See: https://github.com/dhall-lang/dhall-haskell/pull/931-    * See: https://github.com/dhall-lang/dhall-haskell/pull/938-* BUG FIX: Fix merging of sort-level record types-    * The language standard requires that `{ a : Kind } ⩓ { b : Kind }` is-      valid, which this change fixes-    * See: https://github.com/dhall-lang/dhall-haskell/pull/891-* BUG FIX: `dhall freeze` respects the `--ascii` flag-    * See: https://github.com/dhall-lang/dhall-haskell/pull/934-* BUG FIX: Don't autocomplete fields for record types-    * This prevents the REPL from expanding `{ x : T }.<TAB>` to `{ x : T }.x`-    * See: https://github.com/dhall-lang/dhall-haskell/pull/937-* Support `MonadFail`-related changes in GHC 8.8-    * See: https://github.com/dhall-lang/dhall-haskell/pull/912-* Add `cross` flag to simplify cross-compilation-    * This allows the `dhall` package to be built without using-      `TemplateHaskell`-    * See: https://github.com/dhall-lang/dhall-haskell/pull/928-* Increase lines of context for error messages -    * Error messages now provide at least 20 lines of context instead of 3-      before truncating large expressions-    * See: https://github.com/dhall-lang/dhall-haskell/pull/916-* Add line numbers to error messages-    * The bottom of every Dhall type error includes the original source code,-      which now has line numbers on the left margin-    * See: https://github.com/dhall-lang/dhall-haskell/pull/919-* Expand lower bounds on `megaparsec`/`transformers-compat` dependencies-    * This is to support `dhall` on Debian Sid-    * See: https://github.com/dhall-lang/dhall-haskell/pull/939--1.22.0--* Supports version 7.0.0 of the standard-    * See: https://github.com/dhall-lang/dhall-lang/releases/tag/v7.0.0-* BREAKING CHANGE: Add support for empty alternatives-    * The `Union` type now has an optional (`Maybe`) type for each alternative-    * See the changelog for standard version 7.0.0 for more details-    * See: https://github.com/dhall-lang/dhall-haskell/pull/863-* BREAKING CHANGE: Remove support for URL fragments-    * The `URL` type no longer has a field for a URL fragment since the language-      no longer supports fragments-    * See the changelog for standard version 7.0.0 for more details-    * See: https://github.com/dhall-lang/dhall-haskell/pull/851-* BREAKING CHANGE: Remove deprecated `Path` type synonym-    * See: https://github.com/dhall-lang/dhall-haskell/pull/858-* BUG FIX: Correctly parse identifiers beginning with `http`-    * i.e. `httpPort` was supposed to be a valid identifier name and now is-    * See: https://github.com/dhall-lang/dhall-haskell/pull/870-* BUG FIX: Fix `dhall encode` bug-    * `dhall encode` bug was generating binary expressions that were valid-      (i.e. they would decode correctly) but were non-standard (i.e. hashing-      them would not match the hash you would normally get from a semantic-      integrity check)-    * Semantic integrity checks were not affected by this bug since they used-      a slightly different code path that generated the correct binary input to-      the hash.  Only the `dhall decode` subcommand was affected-    * See: https://github.com/dhall-lang/dhall-haskell/pull/859-* BUG FIX: Fix for `Dhall.UnionType`-    * This fixes some expressions that would previously fail to marshal into-      Haskell, specifically those were the marshalling logic was built using-      the `UnionType` utilities-    * See: https://github.com/dhall-lang/dhall-haskell/pull/857-* Feature: New `--alpha` flag to α-normalize command-line output-    * See: https://github.com/dhall-lang/dhall-haskell/pull/855-* Performance improvements-    * The normalizer is now *much* faster-    * See: https://github.com/dhall-lang/dhall-haskell/pull/876--1.21.0--* Supports version 6.0.0 of the language standard-    * See: https://github.com/dhall-lang/dhall-lang/releases/tag/v6.0.0-* BREAKING CHANGE: Remove the `constructors` keyword-    * ... as standardized in version 6.0.0 of the language standard-    * The deprecation cycle is over, so the keyword is no longer supported-    * For more details, see: https://github.com/dhall-lang/dhall-lang/wiki/Migration%3A-Deprecation-of-constructors-keyword-    * See: https://github.com/dhall-lang/dhall-haskell/pull/829-* BREAKING CHANGE: CBOR-encode only special `Double`s as half-floats-    * ... as standardized in version 6.0.0 of the language standard-    * CBOR `Double`s except `Infinity`/`-Infinity`/`NaN`/`0.0` are now encoded in at-      least 32 bits-    * See: https://github.com/dhall-lang/dhall-haskell/pull/822-* BREAKING CHANGE: Sort record and union fields when CBOR-encoding-    * Fields and alternatives are now sorted when serialized-    * This does not affect semantic integrity checks, which already sorted these-      fields/alternatives before hashing expressions-    * This does affect the serialization of expressions that have not been-      normalized (e.g. uninterpreted expressions transmitted over the wire)-    * See: https://github.com/dhall-lang/dhall-haskell/pull/835-* BUG FIX: Fix non-exhaustive pattern match in `dhall lint`-    * This fixes: `Irrefutable pattern failed for pattern Let (l' :| ls') d'`-    * This bug would cause `dhall lint` to fail on some nested `let`/`in`-      expressions-    * See: https://github.com/dhall-lang/dhall-haskell/pull/780-    * See: https://github.com/dhall-lang/dhall-haskell/pull/784-* BUG FIX: Don't fail if `$HOME` environment variable is unset-    * The interpreter was incorrectly throwing an exception if `HOME` was unset-    * The standard requires that implementations should handle the `HOME`-      environment variable being missing-    * See: https://github.com/dhall-lang/dhall-haskell/pull/789-* Feature: Remove version tag from semantic integrity check-    * ... as standardized in version 6.0.0 of the language standard-    * This is not a breaking change because this change also includes-      backwards-compatible support for semantic integrity checks produced by-      older versions of the interpreter-* Feature: Support Unicode path components-    * ... as standardized in version 6.0.0 of the language standard-    * You can now use Unicode in path components if they are quoted-    * i.e. `./families/"禺.dhall"` is now legal-* Feature: Add `Text/show` built-in-    * ... as standardized in version 6.0.0 of the language standard-    * You can now convert a `Text` literal to its equivalent Dhall source code-      (which is itself a `Text` literal)-    * This comes in handy when using Dhall code to generate JSON or Dhall code-    * See: https://github.com/dhall-lang/dhall-haskell/pull/811-* Feature: Add `--immediate-dependencies`/`--transitive-dependencies` flags for-  `dhall resolve`-    * You can now retrieve all of your immediate or transitive dependencies as a-      textual list-    * This simplifies integration with other command-line tools (such as file-      watchers)-    * See: https://github.com/dhall-lang/dhall-haskell/pull/795-    * See: https://github.com/dhall-lang/dhall-haskell/pull/803-* Feature: `dhall freeze` now only freezes remote imports by default-    * `dhall freeze` used to freeze all imports (including local imports and-      environment variables)-    * Now `dhall freeze` only freezes remote imports by default, which is what-      most users want-    * You can install freeze all imports using the `--all` flag-    * See: https://github.com/dhall-lang/dhall-haskell/pull/808-* Feature: `:save` and `:load` REPL state-    * `:save` with no arguments now saves the REPL state to a `.dhall-repl-N`-       file-    * The file format is a list of `dhall repl` commands-    * You can use `:load` to load the saved state back into the REPL-    * See: https://github.com/dhall-lang/dhall-haskell/pull/807-* Feature: Add `:hash` command to `dhall repl`-    * This lets you conveniently hash expressions within the `dhall repl`-    * See: https://github.com/dhall-lang/dhall-haskell/pull/806-* Feature: Add `--check` flag to `dhall format`-    * Use this to check if the input is already formatted-    * Useful for continuous integration when you want to ensure that all code-      under version control remains formatted-    * See: https://github.com/dhall-lang/dhall-haskell/pull/810-* Feature: Add  `UnionInputType` builder for `InputType`s-    * This is the union analog of `RecordInputType`, letting you build a-      record explicitly instead of deriving the instance using GHC generics-    * See: https://github.com/dhall-lang/dhall-haskell/pull/775-* Feature: Add `:set`/`:unset` commands to `dhall repl`-    * You can use these commands to set or unset command-line options-    * Currently only setting/unsetting `--explain` is supported-* Standards-compliance fixes:-    * See: https://github.com/dhall-lang/dhall-haskell/pull/779-    * See: https://github.com/dhall-lang/dhall-haskell/pull/804-    * See: https://github.com/dhall-lang/dhall-haskell/pull/833-* Documentation fixes:-    * See: https://github.com/dhall-lang/dhall-haskell/pull/792-    * See: https://github.com/dhall-lang/dhall-haskell/pull/825-* Test fixes:-    * See: https://github.com/dhall-lang/dhall-haskell/pull/782-    * See: https://github.com/dhall-lang/dhall-haskell/pull/836-* Improved error messages:-    * See: https://github.com/dhall-lang/dhall-haskell/pull/812-    * See: https://github.com/dhall-lang/dhall-haskell/pull/815-    * See: https://github.com/dhall-lang/dhall-haskell/pull/824-* Formatting fixes:-    * See: https://github.com/dhall-lang/dhall-haskell/pull/831-* REPL fixes:-    * See: https://github.com/dhall-lang/dhall-haskell/pull/837--1.20.1--* BUG FIX: Fix binary encoding to use correct standard version-    * This fixes computed hashes to correctly match standard version 5.0.0-    * This is not marked as a breaking change since it is a bug fix.  The-      1.20.0 release will be blacklisted on Hackage and users should upgrade-      from 1.19.* directly to 1.20.1-    * See: https://github.com/dhall-lang/dhall-haskell/pull/771--1.20.0--* Supports version 5.0.0 of the language standard-    * See: https://github.com/dhall-lang/dhall-lang/releases/tag/v5.0.0-* BREAKING CHANGE TO THE LANGUAGE: Implement standardized support for multi-line-  literals-    * This updates the multi-line support to match the standard-    * This is a breaking change because empty lines within the multi-line-      literal now require leading whitespace whereas previously they did not-    * This is also a breaking change because now a newline is required after-      the opening `''` quotes whereas previously it was not required-    * If you use `dhall format` then your multi-line literals already have the-      necessary leading whitespace-* BREAKING CHANGE TO THE LANGUAGE: `constructors x = x`-    * Now the `constructors` keyword behaves like an identity function, since-      constructors can already be accessed as fields off the original union-      type.-    * This is a breaking change since any record of terms that contains a-      `constructors` field will now be a forbidden mixed record of types and-      terms.-    * This is also a breaking change if you annotated the type of what used to-      be a `constructors` record.-    * `dhall lint` will now remove the obsolete `constructors` keyword for you-    * See: https://github.com/dhall-lang/dhall-haskell/pull/693-    * See: https://github.com/dhall-lang/dhall-haskell/pull/701-* BREAKING CHANGE TO THE API: Restore `Parent` constructor for `Local` type-    * This more closely matches the standard and also enables `dhall format` to-      produce a leading `../` for imports instead of `./../`-    * See: https://github.com/dhall-lang/dhall-haskell/pull/718-* BUG FIX: Fix type-checking bug for unions-    * The first fix was that the inferred type was wrong for unions where-      alternatives were types or kinds-    * The second fix was that unions that mixed terms/types/kinds were not-      properly rejected-    * See: https://github.com/dhall-lang/dhall-haskell/pull/763-* BUG FIX: Change how `dhall repl` handles prior definitions-    * This changes the REPL to handle previous bindings as if they were-      defined using a large `let` expression instead of adding them to the-      context-    * This fixes some type-checking false negatives-    * See: https://github.com/dhall-lang/dhall-haskell/pull/729-* Feature: Autocomplete for `dhall repl`-    * You can now auto-complete record fields, union constructors, and-      identifiers that are in scope-    * See: https://github.com/dhall-lang/dhall-haskell/pull/727-* Feature: GHCJS support-    * `dhall` can now be built using GHCJS, although some features are still-      not supported for GHCJS, such as:-        * Semantic integrity checks-        * Custom HTTP headers-    * Also, HTTP imports only work for URLs that support CORS-    * See: https://github.com/dhall-lang/dhall-haskell/pull/739-* Feature: Add support for records of records of types-    * You can now nest records of types-    * See: https://github.com/dhall-lang/dhall-haskell/pull/700-* Feature: Add `:quit` command for `dhall repl`-    * See: https://github.com/dhall-lang/dhall-haskell/pull/719-* Feature: Add `--json` flag for `dhall {encode,decode}`-    * You can now produce/consume CBOR expressions via JSON instead of binary-    * See: https://github.com/dhall-lang/dhall-haskell/pull/717-* Feature: Add decoding logic for `as Text`-    * You can now preserve the `as Text` qualifier on imports when serializing-      them-    * See: https://github.com/dhall-lang/dhall-haskell/pull/712-* Prenormalize substituted expressions-    * This is a performance improvement that reduces the time and memory-      consumption when normalizing expressions-    * See: https://github.com/dhall-lang/dhall-haskell/pull/765--1.19.1---* BUG FIX: Fix serious `dhall lint` bug-    * `dhall lint` would sometimes remove `let` expressions that were still-      in use-    * See: https://github.com/dhall-lang/dhall-haskell/pull/703-* BUG FIX: Fix import caching efficiency bug-    * Some imports were being wastefully fetched multiple times-    * See: https://github.com/dhall-lang/dhall-haskell/pull/702-* Feature: Generate dot graph to visualize import graph-    * Use the `dhall resolve --dot` command-    * See: https://github.com/dhall-lang/dhall-haskell/pull/698-    * See: https://github.com/dhall-lang/dhall-haskell/pull/713-* Improve HTTP error messages-    * See: https://github.com/dhall-lang/dhall-haskell/pull/710--1.19.0--* Supports version 4.0.0 of the language standard-    * See: https://github.com/dhall-lang/dhall-lang/releases/tag/v4.0.0-* BREAKING CHANGE TO THE LANGUAGE AND API: Prevent Hurkens' paradox-    * This fixes a type-checking soundness bug which permitted infinite loops-    * This is a breaking change because infinite loops are no longer possible-    * This is also a breaking change because a record of types is now treated as-      a kind instead of a type-    * See: https://github.com/dhall-lang/dhall-haskell/pull/680-* BREAKING CHANGE TO THE LANGUAGE AND API: `Double`s are now double-precision-  floating point numbers-    * This restricts the range of `Double`s to IEEE 754 double-precision-      floating point-    * This also implies that you can no longer convert `Scientific` values to-      `Dhall` expressions (i.e. no `Inject` instance for `Scientific`)-    * See: https://github.com/dhall-lang/dhall-haskell/pull/667-* BREAKING CHANGE TO THE API: Preserve field order for record projection-    * The API uses a new `Dhall.Set.Set` type instead of `Data.Set.Set`-    * See: https://github.com/dhall-lang/dhall-haskell/pull/670-* BREAKING CHANGE TO THE API: Add support for multi-`let` expressions-    * This changes the `Let` constructor to now support storing multiple-      bindings per `let` expression-    * See: https://github.com/dhall-lang/dhall-haskell/pull/675-* Access constructors as if they were fields of the union type-    * In other words: `< Left : Bool | Right : Natural >.Left`-    * See: https://github.com/dhall-lang/dhall-haskell/pull/657-* Support GHC 8.6-    * See: https://github.com/dhall-lang/dhall-haskell/pull/669-* Add support for quoted path components-    * i.e. `/"foo"/bar/"baz qux"` or `https://example.com/foo/"bar?baz"?qux`-    * See: https://github.com/dhall-lang/dhall-haskell/pull/690-* Fix parsing of `//\\` operator-    * See: https://github.com/dhall-lang/dhall-haskell/commit/9d0fd42d95ab69fa64da4afd8b60d69aca8e65a6-* Preserve Unicode characters when formatting code-    * See: https://github.com/dhall-lang/dhall-haskell/pull/679-* Allow identifier names to begin with `Some`-    * See: https://github.com/dhall-lang/dhall-haskell/pull/658-* Add `subExpressions` `Traversal`-    * See: https://github.com/dhall-lang/dhall-haskell/pull/660-* Add `normalizeWithM` for monadic normalization-    * See: https://github.com/dhall-lang/dhall-haskell/pull/371-* Custom normalizers now take precedence over default normalization logic-    * This allows one to override the implementation of built-in operators-    * See: https://github.com/dhall-lang/dhall-haskell/pull/684--1.18.0--* Supports version 3.0.0 of the language standard:-    * See: https://github.com/dhall-lang/dhall-lang/releases/tag/v3.0.0-* BREAKING CHANGE TO THE LANGUAGE AND API: New `Some`/`None` constructors for-  `Optional` values-    * Example: `[ Some 1, None Natural ]`-    * This is a breaking change to the language because `Some` and `None` are-      now reserved keywords-    * This is a breaking change to the API because `Some` and `None` are new-      constructors for the `Expr` type-* BREAKING CHANGE TO THE LANGUAGE AND API: Support for kind polymorphism-    * This adds a new `Sort` constant above `Kind` in the hierarchy-    * i.e. `Type : Kind : Sort`-    * This is a breaking change to the language because `Sort` is now a-      reserved keyword-    * This is a breaking change to the API because `Sort` is a new-      constructor for the `Expr` type-* BREAKING CHANGE TO THE API: New `Dhall.Map` module-    * This replaces `InsOrdHashMap` in the API-    * The primary motivation is to improve performance and to remove the-      dependency on `insert-ordered-containers`-* BREAKING CHANGE TO THE API: Use standard version instead of protocol version-    * The binary protocol is now versioned alongside the standard-    * The `ProtocolVersion` type is renamed to `StandardVersion` and the-    * `--protocol-version` option is renamed to `--standard-version`-    * See: https://github.com/dhall-lang/dhall-haskell/pull/634-* BUG FIX: Fix import chaining for custom header imports-    * See: https://github.com/dhall-lang/dhall-haskell/pull/618-* BUG FIX: Fix import chaining for imports protected by semantic integrity-  checks-    * See: https://github.com/dhall-lang/dhall-haskell/pull/584-* BUG FIX: Record literals and types produced by `∧`/`⫽`/`⩓` are now sorted-    * This ensures that β-normalization is idempotent-    * See: https://github.com/dhall-lang/dhall-haskell/pull/572-* BUG FIX: `dhall freeze` now correctly handles the starting file being-  located outside the current working directory-    * See: https://github.com/dhall-lang/dhall-haskell/commit/a22aa79d1957be9ecf166ea066e2a9a5b309e1ae-* BUG FIX: Fix parsing of IPv4-mapped IPv6 addresses-    * See: https://github.com/dhall-lang/dhall-haskell/pull/632-* FEATURE: New `--ascii` flag for ASCII output-    * See: https://github.com/dhall-lang/dhall-haskell/pull/570-* FEATURE: New `dhall encode` and `dhall decode` subcommands-    * These allow you to transform Dhall source code to and from its binary-      representation-    * See: https://github.com/dhall-lang/dhall-haskell/pull/588-* LARGE parsing performance improvements-    * Parsing is about 10x-100x faster on most code-    * See: https://github.com/dhall-lang/dhall-haskell/pull/591-    * See: https://github.com/dhall-lang/dhall-haskell/pull/592-    * See: https://github.com/dhall-lang/dhall-haskell/pull/597-    * See: https://github.com/dhall-lang/dhall-haskell/pull/601-    * See: https://github.com/dhall-lang/dhall-haskell/pull/602-    * See: https://github.com/dhall-lang/dhall-haskell/pull/604-    * See: https://github.com/dhall-lang/dhall-haskell/pull/606-* Type-checking performance improvements:-    * See: https://github.com/dhall-lang/dhall-haskell/pull/566-* Normalization performance improvements:-    * See: https://github.com/dhall-lang/dhall-haskell/pull/610-* `dhall freeze` now caches the imports as it freezes them-    * See: https://github.com/dhall-lang/dhall-haskell/pull/587-* `dhall freeze` now refreezes imports with invalid semantic integrity checks-    * See: https://github.com/dhall-lang/dhall-haskell/pull/637-* `dhall freeze` now adds a trailing newline-    * See: https://github.com/dhall-lang/dhall-haskell/pull/629-* Build against `megaparsec-7.0.*`-    * See: https://github.com/dhall-lang/dhall-haskell/pull/565-* Support GHC 8.6-    * See: https://github.com/dhall-lang/dhall-haskell/pull/599-    * See: https://github.com/dhall-lang/dhall-haskell/pull/623-* Support GHC all the way back to 7.10.3-    * See: https://github.com/dhall-lang/dhall-haskell/pull/595-    * See: https://github.com/dhall-lang/dhall-haskell/pull/621-* Improvements to error messages:-    * See: https://github.com/dhall-lang/dhall-haskell/pull/563-    * See: https://github.com/dhall-lang/dhall-haskell/pull/576-    * See: https://github.com/dhall-lang/dhall-haskell/pull/583-    * See: https://github.com/dhall-lang/dhall-haskell/pull/589---1.17.0--* This release corresponds to version 2.0.0 of the language standard-* BREAKING CHANGE TO THE LANGUAGE AND API: Binary serialization support-    * This is a breaking change to the hash for all semantic integrity checks-    * The hash used by the semantic integrity check is now based on the-      binary representation instead of a text representation of the-      expression-    * You can pin the new hashes by supplying the `--protocol-version 1.0`-      option on the command line until you need support for newer language-      features +1.42.3++* [Fix the typechecking rule for `Optional` + `with`](https://github.com/dhall-lang/dhall-haskell/pull/2650)+* [Add `*WithIndex` instances for `Map`](https://github.com/dhall-lang/dhall-haskell/pull/2633)+* [`dhall package`: Add support for automatic sub-packags](https://github.com/dhall-lang/dhall-haskell/pull/2639)+* [`dhall to-directory-tree`: Add `binary-file` support](https://github.com/dhall-lang/dhall-haskell/pull/2641)+* [Support GHC 9.12.1](https://github.com/dhall-lang/dhall-haskell/pull/2649)+* [`dhall to-directory-tree`: create parents of files when using fixpoint representation](https://github.com/dhall-lang/dhall-haskell/pull/2653)++1.42.2++* [Supports standard version 23.1.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v23.1.0)+  * [Allow `Natural` and `Integer` literals in binary notation](https://github.com/dhall-lang/dhall-haskell/pull/2540)+* Fix macOS build [[#2561](https://github.com/dhall-lang/dhall-haskell/pull/2561)] / [[#2586](https://github.com/dhall-lang/dhall-haskell/pull/2586)]+* [`dhall to-directory-tree`: Fix support for empty `Map`s](https://github.com/dhall-lang/dhall-haskell/pull/2609)+* [`Dhall.TH`: Improve recompilation checking](https://github.com/dhall-lang/dhall-haskell/pull/2620)+  * `Dhall.TH` utilities now use `addDependentFile` internally so that GHC will recompile if any Dhall dependencies change+* Performance improvements+  * Optimize `Natural/fold`: [[#2585](https://github.com/dhall-lang/dhall-haskell/pull/2585)] / [[#2596](https://github.com/dhall-lang/dhall-haskell/pull/2596)]+  * [Improve `Dhall.Map.traverseWithKey` performance](https://github.com/dhall-lang/dhall-haskell/pull/2589)+    * The fold will now short-circuit if it reaches a fixed point+  * [#2611](https://github.com/dhall-lang/dhall-haskell/pull/2611)+* Fixes and improvements to test suite+  * [#2593](https://github.com/dhall-lang/dhall-haskell/pull/2593)+* Fixes and improvements to haddocks+  * [#2546](https://github.com/dhall-lang/dhall-haskell/pull/2546)+* Fixes and improvements to code formatting+  * [#2608](https://github.com/dhall-lang/dhall-haskell/pull/2608)++1.42.1++* Add several new entrypoints to `Dhall` module [[#2534](https://github.com/dhall-lang/dhall-haskell/pull/2534)] / [[#2544](https://github.com/dhall-lang/dhall-haskell/pull/2544)]+* Build against latest versions of:+  * [`ansi-terminal`](https://github.com/dhall-lang/dhall-haskell/pull/2521)+  * [`optparse-applicative`](https://github.com/dhall-lang/dhall-haskell/pull/2543)+  * [`optparse-generic`](https://github.com/dhall-lang/dhall-haskell/pull/2519)+  * [`lens`](https://github.com/dhall-lang/dhall-haskell/pull/2539)+  * `template-haskell` [[#2532](https://github.com/dhall-lang/dhall-haskell/pull/2532)] / [[#2542](https://github.com/dhall-lang/dhall-haskell/pull/2542)]+  * [`unix-compat`](https://github.com/dhall-lang/dhall-haskell/pull/2532)+1.42.0++* [Supports standard version 23.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v23.0.0)+  * [BREAKING CHANGE TO THE API AND LANGUAGE: Language support for `Bytes` literals](https://github.com/dhall-lang/dhall-haskell/pull/2499)+    * This is a breaking change to the API due to adding new `Bytes` and `BytesLiteral` constructors to the `Expr` type+    * This is a breaking change to the language now that `Bytes` is a reserved identifier+  * [BREAKING CHANGE TO THE API AND LANGUAGE: New `{Date,Time,TimeZone}/show` builtins](https://github.com/dhall-lang/dhall-haskell/pull/2493)+    * This is a breaking change to the API due to adding new `{Date,Time,TimeZone}Show` constructors to the `Expr` type+    * This is a breaking change to the language now that `{Date,Time,TimeZone}/show` are not reserved identifiers+* [BREAKING CHANGE: `dhall lint` no longer sorts `let` bindings](https://github.com/dhall-lang/dhall-haskell/pull/2503)+  * This had to be removed because the old behavior was not always correct+  * The old behavior would sometimes change the behavior of a Dhall program or break the program+  * Out of an abundance of caution we're disabling the feature until it can be properly fixed (which is't trivial)+* [BUG FIX: Fix pretty-printing of `Time` literals](https://github.com/dhall-lang/dhall-haskell/pull/2466)+  * The pretty-printer was stripping leading zeros from the fractional component+    of seconds+* [BUG FIX: Fix custom normalizers to work for things other than functions](https://github.com/dhall-lang/dhall-haskell/pull/2464)+  * Before this change you could extend the language with custom functions, but+    not custom values (e.g. `foo = 1`)+* [BUG FIX: Don't URL encode path components](https://github.com/dhall-lang/dhall-haskell/pull/2505)+  * The pretty-printer was URL-encoding path components, which is not correct (according to the standard)+  * URL path components are supposed to be already URL-encoded by the user and left undisturbed by the interpreter (which is now what it correctly does)+* New `dhall package` command: [#2478](https://github.com/dhall-lang/dhall-haskell/pull/2487), [#2508](https://github.com/dhall-lang/dhall-haskell/pull/2508)+  * This command makes it easier to turn a directory full of Dhall expressions+    into a dhall package (e.g. `package.dhall`)+* [Improved `dhall to-directory-tree` subcommand](https://github.com/dhall-lang/dhall-haskell/pull/2437)+  * The `dhall to-directory-tree` subcommand now optionally supports specifying+    metadata for generated paths+  * For a worked example, see: https://github.com/dhall-lang/dhall-haskell/blob/main/dhall/examples/to-directory-tree.dhall+* `dhall freeze --cache --all` is now idempotent: [#2486](https://github.com/dhall-lang/dhall-haskell/pull/2486), [#2500](https://github.com/dhall-lang/dhall-haskell/pull/2500)+  * Before this change a second run would fail due to attempting to resolve+    the `missing` import it would generate+* [New Template Haskell options for adding strictness annotations to generated Haskell types](https://github.com/dhall-lang/dhall-haskell/pull/2504)+* [Template Haskell can now generate higher-kinded Haskell types from higher-kinded Dhall types](https://github.com/dhall-lang/dhall-haskell/pull/2506)+* [New `Dhall.Freeze` utilities for working with custom evaluators](https://github.com/dhall-lang/dhall-haskell/pull/2478)+* [Add `Data` instances for `Import` and various other types](https://github.com/dhall-lang/dhall-haskell/pull/2462)+* [Add `Eq` instances for `InvalidDecoder` and `ExtractError`](https://github.com/dhall-lang/dhall-haskell/pull/2482)++1.41.2++* [BUG FIX: Fix `:hash` REPL command to α-normalize input](https://github.com/dhall-lang/dhall-haskell/pull/2420)+* [Add `{From,To}Dhall` instances for `DayOfWeek`](https://github.com/dhall-lang/dhall-haskell/pull/2413)+* [Add `{From,To}Dhall` instances for `ShortText`](https://github.com/dhall-lang/dhall-haskell/pull/2413)+* Performance improvements+  * [#2423](https://github.com/dhall-lang/dhall-haskell/pull/2423)+* Fixes and improvements to haddocks+  * [#2396](https://github.com/dhall-lang/dhall-haskell/pull/2396)+* Fixes and improvements to test suite+  * [#2342](https://github.com/dhall-lang/dhall-haskell/pull/2382)+  * [#2394](https://github.com/dhall-lang/dhall-haskell/pull/2394)+* Build against newer dependencies+  * [`pretty-simple-4.1`](https://github.com/dhall-lang/dhall-haskell/pull/2408)+  * [`aeson-2.1`](https://github.com/dhall-lang/dhall-haskell/pull/2424)+  * [`vector-0.13`](https://github.com/dhall-lang/dhall-haskell/pull/2427)+  * [`turtle-1.6`](https://github.com/dhall-lang/dhall-haskell/pull/2431)++1.41.1++* [BUG FIX: Don't escape `?` path component when pretty-printing `with` expressions](https://github.com/dhall-lang/dhall-haskell/pull/2392)++1.41.0++* [Support standard version 22.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v22.0.0)+  * [Allow `with` expressions to update `Optional` values using `?`](https://github.com/dhall-lang/dhall-haskell/pull/2386)+  * [Add `showConstructor` keyword](https://github.com/dhall-lang/dhall-haskell/pull/2384)+* [BUG FIX: Fix pretty-printing of time zones](https://github.com/dhall-lang/dhall-haskell/pull/2379)+  * Timezones with a negative offset were previously being rendered with two+    leading minus signs instead of one+* [BUG FIX: `dhall freeze --cache` to work with standard version 21.0.0](https://github.com/dhall-lang/dhall-haskell/pull/2350)+  * `dhall freeze` will now use `missing sha256:…` for the first import so that+    the latter import will be tried if the import is not in cache+  * The old behavior is incompatible with standard version 21.0.0 because the+    new behavior of the `?` operator doesn't fall back on hash mismatches+* [BUG FIX: Allow `with` expression to update a field named `Some`](https://github.com/dhall-lang/dhall-haskell/pull/2354)+  * This fixes a discrepancy between the Haskell implementation and the standard+    where the Haskell implementation would not permit+    `{ Some = 0 } with Some = 1 `+* [Fix `dhall {format,lint,freeze}` to preserve leading shebangs](https://github.com/dhall-lang/dhall-haskell/pull/2364)+* [Add `FromDhall` instances for `Int{8,16,32,64}`](https://github.com/dhall-lang/dhall-haskell/pull/2349)++1.40.2++* [Supports standard version 21.1.0](https://github.com/dhall-lang/dhall-haskell/pull/2236)+    * [The interpreter now supports customizing headers using a `headers.dhall`+      configuration file](https://github.com/dhall-lang/dhall-haskell/pull/2236)+    * [Generalize grammar for certain annotations](https://github.com/dhall-lang/dhall-haskell/pull/2320)+    * [Add support for a trailing line comment without a newline](https://github.com/dhall-lang/dhall-haskell/pull/2309)+* [BUG FIX: `dhall repl` no longer ignores type annotations on `:let` commands](https://github.com/dhall-lang/dhall-haskell/pull/2297)+    * Before this fix, `:let x : T = 3` would ignore the `: T` type annotation+* [BUG FIX: Don't accept a bar after an empty union](https://github.com/dhall-lang/dhall-haskell/pull/2338)+    * Before this fix, the interpreter would accept something like `<>|`, which+      is not valid according to the standard grammar+* New `FromDhall`/`ToDhall` instances for `Day`/`TimeOfDay`/`TimeZone` [#2294](https://github.com/dhall-lang/dhall-haskell/pull/2294) [#2300](https://github.com/dhall-lang/dhall-haskell/pull/2300)+    * These types correspond to the recent temporal literals added to the+      language+* [New `subExpressionsWith` `Traversal`](https://github.com/dhall-lang/dhall-haskell/pull/2302)+* [Add Template Haskell support for modifying field names in generated Haskell+  types](https://github.com/dhall-lang/dhall-haskell/pull/2285)+    * This adds a new `makeHaskellTypesWith` utility with takes a+      `GenerateOptions` function argument for customizing the code-generation+      logic+    * This comes in handy when Dhall fields have names are reserved keywords in+      Haskell code.  You can now transform the Haskell field names to avoid+      collisions+* [Support GHC 9.2](https://github.com/dhall-lang/dhall-haskell/pull/2328)+* Fixes and improvements to documentation+    * [#2290](https://github.com/dhall-lang/dhall-haskell/pull/2290)+* Fixes and improvements to error messages+    * [#2303](https://github.com/dhall-lang/dhall-haskell/pull/2303)++1.40.1++* [BUG FIX: Fix equivalence check for `Date` / `Time` / `TimeZone`](https://github.com/dhall-lang/dhall-haskell/pull/2291)+    * This fixes a serious bug in the recently introduced support for temporal+      literals where they would fail to type-check when given a correct type+      annotation or when they were checked against an existing type+    * For example, `00:00:00 : Time` was failing to type-check++1.40.0++* [Almost supports version 20.2.0 of the standard](https://github.com/dhall-lang/dhall-lang/releases/tag/v20.2.0)+    * The main thing that is missing is support for the `headers.dhall` file+    * [BREAKING CHANGE TO THE LANGUAGE: Add support for `Date` / `Time` / `TimeZone` ](https://github.com/dhall-lang/dhall-haskell/pull/2247)+        * This is a breaking change because `Date`, `Time`, and `TimeZone` are+          now reserved identifiers+    * [Improved fallback behavior for `?`](https://github.com/dhall-lang/dhall-haskell/pull/2203)+* [BREAKING CHANGE TO THE LANGUAGE: Require whitespace before `with`](https://github.com/dhall-lang/dhall-haskell/pull/2213)+    * The parser now requires whitespace before the `with` keyword, which brings+      the Haskell implementation into closer compliance with the standard+    * In practice this is a technically breaking change which will not affect+      most programs+* [New `FromDhall` instances for `Predicate`, `Equivalence`, and `Op`](https://github.com/dhall-lang/dhall-haskell/pull/2278)+* [`dhall lint` will now sort `let` bindings with imports](https://github.com/dhall-lang/dhall-haskell/pull/2205)+    * `dhall lint` now reorders `let` bindings to move imports to the top so+      long as doing so does not change the behavior of the program+* Fixes and improvements to code formatting+    * [#2280](https://github.com/dhall-lang/dhall-haskell/pull/2280)+* Fixes and improvements to error messages+    * [#2244](https://github.com/dhall-lang/dhall-haskell/pull/2244)+    * [#2238](https://github.com/dhall-lang/dhall-haskell/pull/2238)++1.39.0++* [Supports version 20.2.0 of the standard](https://github.com/dhall-lang/dhall-lang/releases/tag/v20.2.0)+    * [Add support for Unix shebangs](https://github.com/dhall-lang/dhall-haskell/pull/2175)+* [BREAKING CHANGE TO THE API: `dhall {format,freeze,lint}` now accept multiple+  files](https://github.com/dhall-lang/dhall-haskell/pull/2169)+    * The `--inplace` flag is no longer necessary and you can now specify+      multiple files to update in place on the command line, like+      `dhall format foo.dhall bar.dhall`+    * The `--inplace` flag is still accepted, but does nothing, and will emit a+      warning+    * This is a breaking change to the API for formatting/freezing/linting files+      because now you can specify multiple inputs instead of one input+* [BREAKING CHANGE: Pre-6.0.0 hashes are no longer supported](https://github.com/dhall-lang/dhall-haskell/pull/2190)+    * The interpreter no longer provides backwards compatibility for integrity+      checks computed before standard version 6.0.0+    * This is a breaking change to the API of the `Dhall.Binary` module, where+      certain utilities are no longer parameterized on a `StandardVersion`+    * This is also a breaking change to any Dhall code that depended on these+      really old integrity checks+* [BUG FIX: Formatting `≡` now correctly preserves the original character set](https://github.com/dhall-lang/dhall-haskell/pull/2176)+* [BUG FIX: Don't panic on `Text/replace ""`](https://github.com/dhall-lang/dhall-haskell/pull/2184)+* [Quasiquotation support for Dhall](https://github.com/dhall-lang/dhall-haskell/pull/2198)+    * You can now convert a Dhall expression to the corresponding syntax tree+      using a quasiquoter like this: `[dhall| \x -> x + 2 ]`+* [New `Dhall.Marshal.{Encode,Decode}` modules](https://github.com/dhall-lang/dhall-haskell/pull/2193)+    * These modules split up the `Dhall` module into two smaller modules for+      encoding and decoding logic, respectively+    * The `Dhall` module still re-exports the same functionality as before, so+      this is not a breaking change+* [Support GHC 9.0.1](https://github.com/dhall-lang/dhall-haskell/pull/2154)+* Fixes and improvements to code formatting+    * [Improve pretty-printing of `sha256`](https://github.com/dhall-lang/dhall-haskell/pull/2189)++1.38.1++* [Add `INLINABLE` annotations in more places](https://github.com/dhall-lang/dhall-haskell/pull/2164)+    * This may improve performance by enabling more specializations+* [Fix `hashable`-related test failures](https://github.com/dhall-lang/dhall-haskell/pull/2152)+* [Fix support for GHC 8.4.4](https://github.com/dhall-lang/dhall-haskell/pull/2143)+    * … by using `GeneralizedNewtypeDeriving` (with a `z`)+* [Allow doctest-0.18](https://github.com/dhall-lang/dhall-haskell/pull/2148)+* [Allow bytestring-0.11](https://github.com/dhall-lang/dhall-haskell/pull/2144)++1.38.0++* [BREAKING CHANGE: Detect preferred character set from input](https://github.com/dhall-lang/dhall-haskell/pull/2108)+    * `dhall format` will now preserve the character set of the formatted file+      by default.  In other words, if the file uses ASCII punctuation then+      `dhall format` will format the file using ASCII punctuation.+    * If the file contains both ASCII and Unicode punctuation it will prefer+      Unicode by default+    * This is a breaking change because the `Lam` / `Pi` / `Combine` /+      `CombineTypes`, and `Prefer` constructors now take an additional argument+      to record which character set was used+* [BUG FIX: Fix CORS compliance check](https://github.com/dhall-lang/dhall-haskell/pull/2121)+    * Previous versions were not correctly enforcing CORS compliance+    * This implies that some imports that would have worked previously by+      accident will now fail; specifically: an import from one domain+      transitively importing something from another domain that has not opted+      into CORS+* [Add `ToDhall (Fix f)` instance](https://github.com/dhall-lang/dhall-haskell/pull/2122)+* Fixes and improvements to error messages+    * [#2130](https://github.com/dhall-lang/dhall-haskell/pull/2130)++1.37.1++* [Fix performance regression for `with` expressions](https://github.com/dhall-lang/dhall-haskell/pull/2112)++1.37.0++* [Supports version 20.0.0 of the standard](https://github.com/dhall-lang/dhall-lang/releases/tag/v20.0.0)+    * [Implement revised `Text/replace` β-normalization](https://github.com/dhall-lang/dhall-haskell/pull/2072)+    * [Allow `Text/replace ""` to support an abstract haystack](https://github.com/dhall-lang/dhall-haskell/pull/2084)+    * [Support `if` expressions returning a type or kind](https://github.com/dhall-lang/dhall-haskell/pull/2080)+* BREAKING CHANGE TO THE API: [Improve error message for duplicate projection label](https://github.com/dhall-lang/dhall-haskell/pull/2097)+    * This also makes the implementation more standards-compliant, by treating+      a duplicate label as a type error instead of a parse error+    * This is a breaking change since the `Project` constructor now stores a+      `[Text]` instead of `Set Text`+* [Add `--cache` flag to `dhall hash`](https://github.com/dhall-lang/dhall-haskell/pull/2093)+    * This flag adds the hashed expression to the cache when enabled+* [Deprecate `Inject` / `Interpret`](https://github.com/dhall-lang/dhall-haskell/pull/2099)+    * You should instead use `ToDhall` / `FromDhall`, respectively+* Fixes and improvements to the haddocks:+    * [#2098](https://github.com/dhall-lang/dhall-haskell/pull/2098)+    * [#2100](https://github.com/dhall-lang/dhall-haskell/pull/2100)+* Fixes and improvements to error messages:+    * [#2082](https://github.com/dhall-lang/dhall-haskell/pull/2082)+    * [#2095](https://github.com/dhall-lang/dhall-haskell/pull/2095)+* Fixes and improvements to the parser:+    * [#2083](https://github.com/dhall-lang/dhall-haskell/pull/2089)+* Fixes and improvements to the pretty printer:+    * [#2083](https://github.com/dhall-lang/dhall-haskell/pull/2083)+    * [#2101](https://github.com/dhall-lang/dhall-haskell/pull/2101)++1.36.0++* [Supports version 19.0.0 of the standard](https://github.com/dhall-lang/dhall-lang/releases/tag/v19.0.0)+    * BREAKING CHANGE TO THE API: [Add `Text/replace` built-in](https://github.com/dhall-lang/dhall-haskell/pull/2063)+    * [Implement `with` without syntactic sugar](https://github.com/dhall-lang/dhall-haskell/pull/2055)+* [`dhall lint` will now add a `.dhall` extension to all Prelude imports](https://github.com/dhall-lang/dhall-haskell/pull/2061)+    * The old extension-free Prelude imports are deprecated+* [Fix command-line completions for files](https://github.com/dhall-lang/dhall-haskell/pull/2016)+* [Improve Template Haskell support for record constructors](https://github.com/dhall-lang/dhall-haskell/pull/2070)+* Fixes and improvements to code formatting+    * [#2037](https://github.com/dhall-lang/dhall-haskell/pull/2037)+    * [#2048](https://github.com/dhall-lang/dhall-haskell/pull/2048)+    * [#2069](https://github.com/dhall-lang/dhall-haskell/pull/2069)++1.35.0++* [Supports version 18.0.0 of the standard](https://github.com/dhall-lang/dhall-lang/releases/tag/v18.0.0)+    * [Implement more efficient `with` desugaring](https://github.com/dhall-lang/dhall-haskell/pull/1993)+        * Chained `with` expressions will now be much more efficient+* [BREAKING CHANGE TO THE API: Preserve whitespace for `Lam` constructor](https://github.com/dhall-lang/dhall-haskell/pull/1980)+    * This change extends the `Lam` constructor to preserve whitespace around+      the variable binding+    * The motivation for this change is to enable `dhall-docs` to support+      jumping to definitions+    * You can replace your existing `Lam` constructors with+      `Dhall.Core.makeFunctionBinding`+* [BREAKING CHANGE TO THE API: Preserve whitespace for `Field` constructors](https://github.com/dhall-lang/dhall-haskell/pull/1991)+    * This change extends the `Field` constructor to preserve whitespace around+      the selected field+    * The motivation for this change is to enable `dhall-docs` to support+      jumping to definitions+    * You can use `Dhall.Core.makeFieldSelection` and+      `Dhall.Core.fieldSelectionLabel` to convert between the detailed and the+      simple representation of the selected field.+* [Add `FromDhall` instances for `{Int,Word}{,8,16,32,64}`](https://github.com/dhall-lang/dhall-haskell/pull/2012)+* [Add `--output` option for `dhall text` subcommand](https://github.com/dhall-lang/dhall-haskell/pull/1974)+* [Add `Dhall.Crypto.toString`](https://github.com/dhall-lang/dhall-haskell/pull/1976)+* [Make the HTTP `Manager` configurable](https://github.com/dhall-lang/dhall-haskell/pull/2027)+    * Several import-related functions now provide an alternative variants that+      allows the user to supply a custom `Manager`+    * You can use this to tweak HTTP request timeouts or use a different TLS+      manager (e.g. one from `http-client-openssl`)+* Fixes and improvements to code formatting+    * [#2000](https://github.com/dhall-lang/dhall-haskell/pull/2000)+    * [#2021](https://github.com/dhall-lang/dhall-haskell/pull/2021)++      The formatter now preserves comments for record fields (both record types+      and record literals)+* Fixes and improvements to documentation+    * [#2011](https://github.com/dhall-lang/dhall-haskell/pull/2011)+    * [#2013](https://github.com/dhall-lang/dhall-haskell/pull/2013)+    * [#2014](https://github.com/dhall-lang/dhall-haskell/pull/2014)+* Fixes and improvements to test suite+    * [#2020](https://github.com/dhall-lang/dhall-haskell/pull/2020)++1.34.0++* [Supports version 17.1.0 of the standard](https://github.com/dhall-lang/dhall-lang/releases/tag/v17.1.0)+    * [Add support for trailing commas](https://github.com/dhall-lang/dhall-haskell/pull/1885)+* BREAKING CHANGE to the API: [Support prefix comments on record key-value pairs](https://github.com/dhall-lang/dhall-haskell/pull/1908)+    * The Dhall AST (i.e. `Expr`) now preserves some comments for record types+      and record literals+    * The impact of this change is that you will need to add+      `Dhall.Syntax.makeRecordField` or `Dhall.Syntax.recordFieldValue` in a few+      places wherever your Haskell assembles or disassembles record expressions+    * The motivation of this change is two-fold:+        * To eventually enable `dhall-docs` support for rendering record+          comments as documentation+        * To eventually enable support for preserving record-related comments+          when formatting Dhall code+* BUG FIX: [Fix `with` expressions to permit functions on their left-hand side](https://github.com/dhall-lang/dhall-haskell/pull/1897)+    * This was a case of the Haskell implementation not being compliant with the+      standard grammar+* [Drop support for GHC 8.2](https://github.com/dhall-lang/dhall-haskell/pull/1949)+* [Add a new `dhall rewrite-with-schemas` command](https://github.com/dhall-lang/dhall-haskell/pull/1902)+    * You can now simplify a Dhall expression using a schema record (e.g. a+      `./schemas.dhall` record that a package might provide)+    * This simplification replaces large anonymous records with an+      equivalent use of a record completion when possible+* [Add `--transitive` flag to `dhall {format,lint,freeze}](https://github.com/dhall-lang/dhall-haskell/pull/1880)+    * This flag lets you format/lint/freeze a file and all of its transitive+      dependencies that are reachable via relative file imports+* [Move `man/dhall.1` to `data-files`](https://github.com/dhall-lang/dhall-haskell/pull/1921)+    * This ensures that Cabal will install `dhall`'s `man` pages in the+      correct directory+* Performance improvements+    * [#1879](https://github.com/dhall-lang/dhall-haskell/pull/1879)+* Standards compliance+    * [#1953](https://github.com/dhall-lang/dhall-haskell/pull/1953)+    * [#1954](https://github.com/dhall-lang/dhall-haskell/pull/1954)+    * [#1956](https://github.com/dhall-lang/dhall-haskell/pull/1956)+    * [#1957](https://github.com/dhall-lang/dhall-haskell/pull/1957)+    * [#1958](https://github.com/dhall-lang/dhall-haskell/pull/1958)+* Fixes and improvements to haddocks+    * [#1881](https://github.com/dhall-lang/dhall-haskell/pull/1881)+    * [#1955](https://github.com/dhall-lang/dhall-haskell/pull/1955)++1.33.1++* [Multi-line REPL / support `repline-0.4.0.0`](https://github.com/dhall-lang/dhall-haskell/pull/1867)+    * `dhall repl` supports a new `:paste` command that lets you input a command+       by pasting one or more lines++1.33.0++* [Supports version 17.0.0 of the standard](https://github.com/dhall-lang/dhall-lang/releases/tag/v17.0.0)+    * BREAKING CHANGE: [URLs no longer support quoted path components](https://github.com/dhall-lang/dhall-haskell/pull/1812)+    * BREAKING CHANGE: [`Optional/{fold,build}` are no longer built-ins](https://github.com/dhall-lang/dhall-haskell/pull/1802)+    * [Record fields now permit empty labels](https://github.com/dhall-lang/dhall-haskell/pull/1812)+* BREAKING CHANGE: [Fail instead of hanging when deriving `FromDhall` for recursive types](https://github.com/dhall-lang/dhall-haskell/pull/1825)+    * This is a breaking change as now the `expected` type returns an+      `Expector (Expr Src Void)` (essentially an `Either`) instead of+      `Expr Src Void`+    * If you really don't want to handle the new error-related wrapper, you can+      get the old behavior using a partial pattern match (which will be partial,+      still an improvement over the previous behavior, which was hanging)+* BREAKING CHANGE: [Records can no longer contain attributes named after language keywords](https://github.com/dhall-lang/dhall-haskell/pull/1801)+    * This is a bugfix, because the language standard disallows using+      keywords as record labels. However, some users were relying on+      this bug.+    * If you need to use a keyword as a record label, enclose it in backticks:+      ``{ `assert` = 1 }``.+* [Fix invalid cache entries](https://github.com/dhall-lang/dhall-haskell/pull/1793)+    * The interpreter will now correct cached expressions that are incorrect+      and warn you when this happens+    * Specifically, if there is a hash mismatch from the cached expression the+      interpreter will resolve the import again and fix the cache if the+      resolved import matches the expected hash+* [Make `encodeExpression` polymorphic](https://github.com/dhall-lang/dhall-haskell/pull/1789)+    * `encodeExpression` now has a more general type, which means that you+      can use it to serialise expressions without imports (i.e.+      ones of type `Expr Void Void`)+* [Add `--quiet` option for `dhall decode`](https://github.com/dhall-lang/dhall-haskell/pull/1803)+* [Add `--noted` flag for `dhall haskell-syntax-tree`](https://github.com/dhall-lang/dhall-haskell/pull/1843)+* Performance improvements:+    * There were several performance improvements related to binary decoding,+      which should improve cache lookup speed+    * [#1807](https://github.com/dhall-lang/dhall-haskell/pull/1807)+    * [#1809](https://github.com/dhall-lang/dhall-haskell/pull/1809)+    * [#1857](https://github.com/dhall-lang/dhall-haskell/pull/1857)+* Improvements to error messages+    * [#1824](https://github.com/dhall-lang/dhall-haskell/pull/1824)+    * [#1849](https://github.com/dhall-lang/dhall-haskell/pull/1849)+    * [#1851](https://github.com/dhall-lang/dhall-haskell/pull/1851)+* Fixes to haddocks+    * [#1815](https://github.com/dhall-lang/dhall-haskell/pull/1815)++1.32.0++* [Supports version 16.0.0 of the standard](https://github.com/dhall-lang/dhall-lang/releases/tag/v16.0.0)+    * BREAKING CHANGE: Change the precedence of `with` and `===`+        * The precedence change to `with` means that some old expressions that+          were valid now require explicit parentheses+    * BREAKING CHANGE: Use RFC7049bis encoding for `Double`s+        * This is a breaking change because the hashes of expressions with small+          `Double` literals will change now+    * Add support for unions mixing terms and types+        * For example, `< A : Bool | B : Type >` is legal now+        * You can now write `someRecord with a.b.c = x` to update a nested+          fields+* DEPRECATION: [Deprecate `Dhall.Parser.exprA`](https://github.com/dhall-lang/dhall-haskell/pull/1740)+    * `Dhall.Parser` module will eventually drop support for parsing custom+      import types+    * This is necessary in order to fix several parsing bugs and improve+      parsing error messages+* BUG FIX: [GHC Generics instance for `:+:` now uses `union`](https://github.com/dhall-lang/dhall-haskell/pull/1725)+    * This fixes a few subtle bugs in how Dhall unions are marshalled into+      Haskell types, and also improves the error messages+* Formatting improvements+    * [Change formatting of `if` expressions](https://github.com/dhall-lang/dhall-haskell/pull/1767)+    * [Change formatting for functions and their types](https://github.com/dhall-lang/dhall-haskell/pull/1759)+    * [Prefer puns when formatting record completions](https://github.com/dhall-lang/dhall-haskell/pull/1736)+* [Convert union alternatives to directory tree](https://github.com/dhall-lang/dhall-haskell/pull/1757)+    * `dhall to-directory-tree` now supports unions which are automatically+      unwrapped+* [Fix `dhall freeze --cache` to better handle protected imports](https://github.com/dhall-lang/dhall-haskell/pull/1772)+    * `dhall freeze --cache` will now also update imports that already have+      integrity checks+* [Don't normalized partially saturated `{List,Natural}/fold`](https://github.com/dhall-lang/dhall-haskell/pull/1742)+    * The behavior now matches the standard.  Previously, the Haskell+      implementation was not standards-compliant because it would normalize+      these partially saturated built-ins++1.31.1++* BUG FIX: [Allow whitespace after record pun entry](https://github.com/dhall-lang/dhall-haskell/pull/1733)+    * The record pun feature introduced in the previous release did not+      correctly parse record puns with trailing whitespace, which this change+      fixes.+* [Expose `{default,}InputNormalizer`](https://github.com/dhall-lang/dhall-haskell/pull/1727)+    * The previous version introduced a breaking change to the `autoWith` type+      that required access to the implementation of `InputNormalizer`, which was+      not exported.  This change fixes that.+* Build against latest dependencies+    * [`QuickCheck-2.14`](https://github.com/dhall-lang/dhall-haskell/pull/1721)+    * [`haskell-lsp-0.21`](https://github.com/dhall-lang/dhall-haskell/pull/1730)+    * [`repline-0.3` / `haskeline-0.8`](https://github.com/dhall-lang/dhall-haskell/pull/1717)+    * [`template-haskell-2.16`](https://github.com/dhall-lang/dhall-haskell/pull/1719)+* [Prefer to format using record puns when possible](https://github.com/dhall-lang/dhall-haskell/pull/1729)+    * `dhall format` will now reformat code to use record puns when applicable+* Fixes and improvements to error messages:+    * [#1721](https://github.com/dhall-lang/dhall-haskell/pull/1724)++1.31.0++* [Supports version 15.0.0 of the standard](https://github.com/dhall-lang/dhall-lang/releases/tag/v15.0.0)+    * [Implement `with` keyword](https://github.com/dhall-lang/dhall-haskell/pull/1685)+        * You can now write `someRecord with a.b.c = x` to update a nested+          fields+    * [Add support for record puns](https://github.com/dhall-lang/dhall-haskell/pull/1710)+        * You can now write `{ x, y }` as a shorthand for `{ x = x, y = y }`+* BREAKING CHANGE TO THE API: [Auto-derive `Generic`/`FromDhall`/`ToDhall` with Template Haskell](https://github.com/dhall-lang/dhall-haskell/pull/1682)+    * Now the `Dhall.TH.makeHaskell*` utilities will include these derived+      instances in the generated declarations+    * This is a breaking change since users were likely already generating these+      instances separately, which will now conflict with the included instances+* BREAKING CHANGE TO THE API: [`From/ToDhall` no longer takes `InterpretOptions` argument](https://github.com/dhall-lang/dhall-haskell/pull/1696)+    * The types of the `autoWith` and `injectWith` methods have changed to+      take an `InputNormalizer` instead of an `InterpretOptions`+        * Note that `InputNormalizer` is a subset of `InterpretOptions`+    * This is a breaking change to how derived `FromDhall` / `ToDhall` instances+      are customized to more closely match how other Haskell packages customize+      derived instances (e.g. `aeson` with `FromJSON` / `ToJSON`)+        * Previously you would customize the behavior globally by passing in+          a top-level `InterpretOptions` record to `autoWith`+        * Now you can customize the behavior locally on a per-instance basis+    * This change enables the following change ...+* [Add `Dhall.Deriving` module for `deriving-via` helpers](https://github.com/dhall-lang/dhall-haskell/pull/1700)+    * Now you can take advantage of the `-XDerivingVia` language extension to+      customize derived `FromDhall`/`ToDhall` instances, like this:+        * `deriving (FromDhall, ToDhall) via Codec (SetSingletonConstructors Bare) Name`+* BREAKING CHANGE TO THE LANGUAGE: [Match standard with respect to `using toMap`](https://github.com/dhall-lang/dhall-haskell/pull/1673)+    * `https://example.com using toMap customHeaders` is now a parse error+      and needs to be explicitly parenthesized as+      `https://example.com using (toMap customHeaders)`+    * The language standard had always required the parentheses, but the Haskell+      implementation was not correctly matching the standard+* [Fix formatting of indented comments containing empty lines](https://github.com/dhall-lang/dhall-haskell/pull/1688)+    * `dhall format` was previously not idempotent when formatting indented+      comments with empty lines+    * Specifically, the formatter kept indenting things further with each+      format, which this change fixes+* [Fix pretty-printer to preserve original numeric literals](https://github.com/dhall-lang/dhall-haskell/pull/1674)+    * Now `dhall format` will preserve numeric literals exactly how you wrote+      them+    * For example, `0xFF` will no longer be reformatted as `255`+* [Add `dhall to-directory-tree` support for `Map`s](https://github.com/dhall-lang/dhall-haskell/pull/1705)+    * `Map`s are now converted to directories (just like records)+* [Add manpage](https://github.com/dhall-lang/dhall-haskell/pull/1677)+    * ... mainly for the benefit of people packaging Dhall for various+      distributions+* [Group commands in CLI](https://github.com/dhall-lang/dhall-haskell/pull/1692)+    * The command-line `--help` output now groups commands into useful+      sections+* [Fix numeric parsing for GHCJS](https://github.com/dhall-lang/dhall-haskell/pull/1681)+    * The GHCJS backend for Dhall was failing to parse numbers, which this+      change fixes+* Fixes and improvements to error messages:+    * [#1656](https://github.com/dhall-lang/dhall-haskell/pull/1656)+    * [#1698](https://github.com/dhall-lang/dhall-haskell/pull/1698)+    * [#1702](https://github.com/dhall-lang/dhall-haskell/pull/1702)+* Fixes and improvements to the haddocks:+    * [#1708](https://github.com/dhall-lang/dhall-haskell/pull/1708)+    * [#1712](https://github.com/dhall-lang/dhall-haskell/pull/1712)++1.30.0++* [Supports version 14.0.0 of the standard](https://github.com/dhall-lang/dhall-lang/releases/tag/v14.0.0)+* BREAKING CHANGE TO THE API: [Add `--check` flag to `dhall {lint,freeze}`](https://github.com/dhall-lang/dhall-haskell/pull/1636)+    * You can now use the `--check` flag to verify that a file has already been+      linted or frozen+    * This is a breaking change to the types used by the `Dhall.Format` module+* BREAKING CHANGE TO THE LANGUAGE: [Disallow `Natural` literals with leading zeros](https://github.com/dhall-lang/dhall-haskell/pull/1658)+    * Now a literal like `042` is no longer valid+    * See the [changelog for standard version 14.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v14.0.0) for more details+* BUG FIX: [Fix parsing of `Double` literal trailing whitespace](https://github.com/dhall-lang/dhall-haskell/pull/1647)+    * Certain expressions using `Double` literals would fail to parse, which this+      change fixes+* BUG FIX: [Use `DeriveLift` instead of GHC Generics to derive `Lift` ](https://github.com/dhall-lang/dhall-haskell/pull/1640)+    * This fixes a build failure on GHC 8.10+* [Drop support for GHC 7.10.3](https://github.com/dhall-lang/dhall-haskell/pull/1649)+    * GHC 8.0.2 is now the earliest supported version+* [Add support for dotted field syntax](https://github.com/dhall-lang/dhall-haskell/pull/1651)+    * `{ x.y.z = 1 }` now legal syntax for nested fields+    * See the [changelog for standard version 14.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v14.0.0) for more details+* [Add support for duplicate record fields](https://github.com/dhall-lang/dhall-haskell/pull/1643)+    * This combines with the previous feature to let you write+      `{ x.y = 1, x.z = True }`, which is equivalent to+      `{ x = { y = 1, z = True } }`+    * See the [changelog for standard version 14.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v14.0.0) for more details+* [Add `dhall lint` support for deprecating `Optional/{fold,build}`](https://github.com/dhall-lang/dhall-haskell/pull/1628)+    * The `Optional/{fold,build}` built-ins are deprecated and can be implemented+      in terms of other language features+    * `Optional/fold` can be implemented in terms of `merge` (which now works on+      `Optional` values)+    * `Optional/build` could always be implemented using `Some`/`None`+    * `dhall lint` now transforms the deprecated built-ins to use their+      equivalent built-in-free versions+* [Support Template Haskell for multiple datatypes](https://github.com/dhall-lang/dhall-haskell/pull/1664)+    * This extends the Template Haskell support added in the previous release to+      work for datatypes that refer to one another+* [Add support for custom substitutions](https://github.com/dhall-lang/dhall-haskell/pull/1650)+    * You can now add custom substitutions, which are like `let` bindings that+      propagate to transitive imports+* [Small formatting fixes](https://github.com/dhall-lang/dhall-haskell/pull/1652)++1.29.0++* [Supports version 13.0.0 of the standard](https://github.com/dhall-lang/dhall-lang/releases/tag/v13.0.0)+* BREAKING CHANGE: [Generate Haskell datatype declarations from Dhall types](https://github.com/dhall-lang/dhall-haskell/commit/b0280826790930d18a5498fb802120478fa11767#diff-a9729dccf50be61ce3d8c68c16f0fd50)+    * You can now use the `makeHaskellTypeFromUnion` Template Haskell utility+      to generate a Haskell datatype declaration from a Dhall union type+    * This helps ensure that your Haskell types and Dhall types stay in sync,+      when you want the Dhall type to be the source of truth+    * This is a breaking change because the default `InterpretOptions` changed+      the default handling of singleton constructors from `Wrapped` to `Smart`+    * You can preserve the old behavior using:+      `autoWith defaultInterpretOptions{ singletonConstructors = Wrapped }`+* BUG FIX: [Fix `dhall freeze --cache` and `dhall lint` to preserve `let`-related comments](https://github.com/dhall-lang/dhall-haskell/pull/1597)+    * Now they match the behavior of `dhall format` with regard to preserving+      these comments+* BUG FIX: [Fix escaping of significant leading whitespace when formatting code](https://github.com/dhall-lang/dhall-haskell/pull/1598)+    * The formatter would sometimes unnecessarily escape significant leading+      whitespace for the final line of multiline string literals, which this+      change fixes+* BUG FIX: [Fix `dhall encode --json` for `Double` values](https://github.com/dhall-lang/dhall-haskell/issues/1350)+* NEW FEATURE: [`dhall to-directory-tree` command](https://github.com/dhall-lang/dhall-haskell/pull/1606)+    * You can now generate a directory tree from a Dhall expression+    * Specifically:+        * records are converted to directories+        * `Text` fields are converted to files named after the field+        * `Optional` values are omitted if `None`+        * Everything else is rejected+* NEW FEATURE: [Hexadecimal literals](https://github.com/dhall-lang/dhall-haskell/pull/1607)+    * See the [changelog for standard version 13.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v13.0.0) for more details+* NEW FEATURE: [`merge` works on `Optional` values](https://github.com/dhall-lang/dhall-haskell/pull/1608)+    * See the [changelog for standard version 13.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v13.0.0) for more details+* [Improve formatter](https://github.com/dhall-lang/dhall-haskell/pull/1609)+    * `dhall format` will now render expressions nested inside record fields or+      alternatives more compactly, including:+        * Records+        * Record completion expressions+        * Expressions wrapped in `Some`+        * Lists+* [Exclude the `using ...` suffix from imports listed by `dhall resolve`](https://github.com/dhall-lang/dhall-haskell/pull/1603)+    * Specifically when using the `--{immediate,transitive}-dependencies` flags++1.28.0++* [Supports version 12.0.0 of the standard](https://github.com/dhall-lang/dhall-lang/releases/tag/v12.0.0)+* BREAKING CHANGE: [Add `Integer/{clamp,negate}` built-ins](https://github.com/dhall-lang/dhall-haskell/pull/1486)+    * This is a technically breaking change API since this adds a new+      constructor to the `Expr` type+    * This is also a technically breaking change to the language.  See the [changelog for standard version 12.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v12.0.0) for more details+* BREAKING CHANGE: [Remove support for fusion](https://github.com/dhall-lang/dhall-haskell/pull/1478)+    * This is also a technically breaking change to the language.  See the [changelog for standard version 12.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v12.0.0) for more details+* BREAKING CHANGE: [Parse whitespace more precisely](https://github.com/dhall-lang/dhall-haskell/pull/1483)+    * The Haskell implementation now matches the official grammar much more+      closely, but as a result will now reject some programs that it used to+      accept+    * For example, `1:Natural` used to be valid and now is no longer valid as+      the standard requires mandatory whitespace after the `:`+    * Consult the [standard grammar](https://github.com/dhall-lang/dhall-lang/blob/master/standard/dhall.abnf) if you run into a new parsing error as a result of this change+    * This is also a parsing performance regression (specifically for parsing+      comments), but should not be noticeable in practice.  See [#1512](https://github.com/dhall-lang/dhall-haskell/pull/1512) for more details+* BREAKING CHANGE: Rename `Type` to `Decoder` and `InputType` to `Encoder` [#1483](https://github.com/dhall-lang/dhall-haskell/pull/1485) / [#1489](https://github.com/dhall-lang/dhall-haskell/pull/1489)+* BUG FIX: [Fix `dhall format --check`](https://github.com/dhall-lang/dhall-haskell/pull/1462)+    * Before this change `dhall format --check` would fail due to attempting to+      read all of standard input in twice+* BUG FIX: [Fix `dhall freeze` to always re-freeze an import](https://github.com/dhall-lang/dhall-haskell/pull/1471)+    * Before this fix, `dhall freeze` would not attempt to refreeze an already+      frozen import+* [Permit spaces around completion operator](https://github.com/dhall-lang/dhall-haskell/pull/1532)+    * See the [changelog for standard version 12.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v12.0.0) for more details+* [Make `missing` referentially transparent](https://github.com/dhall-lang/dhall-haskell/pull/1509)+    * `missing` can now be imported transitively via a remote import+    * Normally resolving `missing` would still still fail, except for+      `missing as Location`, which is now a valid transitive import+    * See the [changelog for standard version 12.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v12.0.0) for more details+* [Write cache files atomically](https://github.com/dhall-lang/dhall-haskell/pull/1544)+    * This is a resilience improvement so that the cache is not left in a+      corrupt state in the event of a power outage or exhausting disk/memory+* [New `Dhall.function` utility](https://github.com/dhall-lang/dhall-haskell/pull/1507)+    * This is provides the same functionality as the `Interpret` instance for+      `(->)`, except without the use of typeclasses+* [New `dhall haskell-syntax-tree` command](https://github.com/dhall-lang/dhall-haskell/pull/1553)+    * This command displays the Haskell syntax tree of an expression+      (primarily for debugging purposes)+    * Note that this is highly-volatile and subject to change, so don't depend+      on this programmatically.  We may break the output of this command without+      any notice.+* [Add `instance Show Ann`](https://github.com/dhall-lang/dhall-haskell/pull/1567)+* [Move normalization code from `Dhall.Core` to `Dhall.Normalize`](https://github.com/dhall-lang/dhall-haskell/pull/1452)+    * Note that this is not a breaking change.  The relocated utilities are+      still re-exported from `Dhall.Core`+* [Fix `dhall resolve --transitive-dependencies` to list dependencies in "post-order"](https://github.com/dhall-lang/dhall-haskell/pull/1539)+* Performance improvements+    * [#1500](https://github.com/dhall-lang/dhall-haskell/pull/1500)+    * [#1522](https://github.com/dhall-lang/dhall-haskell/pull/1522)+    * [#1568](https://github.com/dhall-lang/dhall-haskell/pull/1568)+    * [#1580](https://github.com/dhall-lang/dhall-haskell/pull/1578)+* Fixes and improvements to code formatting+    * [#1460](https://github.com/dhall-lang/dhall-haskell/pull/1460)+    * [#1466](https://github.com/dhall-lang/dhall-haskell/pull/1466)+    * [#1508](https://github.com/dhall-lang/dhall-haskell/pull/1508)+    * [#1527](https://github.com/dhall-lang/dhall-haskell/pull/1527)+    * [#1422](https://github.com/dhall-lang/dhall-haskell/pull/1422)+    * [#1552](https://github.com/dhall-lang/dhall-haskell/pull/1552)+    * [#1543](https://github.com/dhall-lang/dhall-haskell/pull/1543)+    * [#1554](https://github.com/dhall-lang/dhall-haskell/pull/1554)+    * [#1569](https://github.com/dhall-lang/dhall-haskell/pull/1569)+* Fixes and improvements to code linting+    * [#1518](https://github.com/dhall-lang/dhall-haskell/pull/1518)+    * [#1531](https://github.com/dhall-lang/dhall-haskell/pull/1531)+* Fixes and improvements to error messages+    * [#1443](https://github.com/dhall-lang/dhall-haskell/pull/1443)+    * [#1448](https://github.com/dhall-lang/dhall-haskell/pull/1448)+    * [#1482](https://github.com/dhall-lang/dhall-haskell/pull/1482)+    * [#1519](https://github.com/dhall-lang/dhall-haskell/pull/1519)+    * [#1556](https://github.com/dhall-lang/dhall-haskell/pull/1556)+    * [#1528](https://github.com/dhall-lang/dhall-haskell/pull/1528)+* Fixes and improvements to the parser+    * [#1473](https://github.com/dhall-lang/dhall-haskell/pull/1473)+    * [#1549](https://github.com/dhall-lang/dhall-haskell/pull/1549)+    * [#1563](https://github.com/dhall-lang/dhall-haskell/pull/1563)+    * [#1584](https://github.com/dhall-lang/dhall-haskell/pull/1584)+* Fixes and improvements to diffs+    * [#1585](https://github.com/dhall-lang/dhall-haskell/pull/1585)+* Fixes and improvements to the REPL+    * [#1573](https://github.com/dhall-lang/dhall-haskell/pull/1573)+* Fixes and improvements to documentation+    * [#1530](https://github.com/dhall-lang/dhall-haskell/pull/1530)++1.27.0++* [Supports version 11.0.0 of the standard](https://github.com/dhall-lang/dhall-lang/releases/tag/v11.0.0)+* BREAKING CHANGE: Rename `Inject`/`Interpret` to `ToDhall`/`FromDhall`+    * This change `ConstraintKinds` to minimize disruption by keeping around+      `Inject`/`Interpret` as synonyms for `ToDhall`/`FromDhall`+    * In other words, constraints and derived instances using `Inject` or+      `Interpret` will still work+    * However, manual instances using `Inject` or `Interpret` won't work+      unless you rename them to `ToDhall`/`FromDhall` or enable the+      `TypeSynonymInstances` extension+* BREAKING CHANGE: Fix `Eq` instance for `Expr`s with special `Double`s+    * This fixes the `Eq` instance for `Expr`s to match the standard regarding+      `Double` comparisons+    * Specifically: `NaN == NaN` and `-0.0 /= 0.0`+    * This is a breaking change because the `DoubleLit` constructor of `Expr`+      now stores a `DhallDouble` instead of a `Double`+* BREAKING CHANGE: [Add `--file` option for `dhall hash`](https://github.com/dhall-lang/dhall-haskell/pull/1445)+    * This is a breaking change because it also removes the `Dhall.Hash` module,+      which wasn't really carrying its own weight+* [Add support for leading separators](https://github.com/dhall-lang/dhall-haskell/pull/1355)+    * See the [changelog for standard version 11.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v11.0.0) for more details+* [Add record completion operator](https://github.com/dhall-lang/dhall-haskell/pull/1375)+    * See the [changelog for standard version 11.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v11.0.0) for more details+* [Add `dhall tags` subcommand](https://github.com/dhall-lang/dhall-haskell/pull/1398)+    * This generates an ETags file from an input file or directory+* [Add `dhall lint` support for fixing malformed assertions](https://github.com/dhall-lang/dhall-haskell/pull/1353)+    * `dhall lint` now fixes `let example = foo === bar` to be+       `let example = assert : foo === bar`+* Normalize inferred types [#1337](https://github.com/dhall-lang/dhall-haskell/pull/1337)+* New `FromDhall`/`ToDhall` (previously `Interpret`/`Inject`) instances for:+    * [`Void`](https://github.com/dhall-lang/dhall-haskell/pull/1382)+    * `Map` [#1391](https://github.com/dhall-lang/dhall-haskell/pull/1391) / [#1412](https://github.com/dhall-lang/dhall-haskell/pull/1412)+    * [`HashMap`](https://github.com/dhall-lang/dhall-haskell/pull/1426)+    * [`Set` and `HashSet`](https://github.com/dhall-lang/dhall-haskell/pull/1405)+    * [`()`](https://github.com/dhall-lang/dhall-haskell/pull/1388)+* [Add `--output` option to `dhall`](https://github.com/dhall-lang/dhall-haskell/pull/1399)+* [Move syntax things from `Dhall.Core` to a new `Dhall.Syntax` module](https://github.com/dhall-lang/dhall-haskell/pull/1440)+    * This is not a breaking change.  `Dhall.Core` still re-exports the same+      API as before+* Performance improvements+    * [#1362](https://github.com/dhall-lang/dhall-haskell/pull/1362)+    * [#1366](https://github.com/dhall-lang/dhall-haskell/pull/1366)+    * [#1368](https://github.com/dhall-lang/dhall-haskell/pull/1368)+    * [#1397](https://github.com/dhall-lang/dhall-haskell/pull/1397)+    * [#1401](https://github.com/dhall-lang/dhall-haskell/pull/1401)+* Fixes and improvements to code formatting+    * [#1360](https://github.com/dhall-lang/dhall-haskell/pull/1360)+    * [#1372](https://github.com/dhall-lang/dhall-haskell/pull/1372)+    * [#1380](https://github.com/dhall-lang/dhall-haskell/pull/1380)+    * [#1415](https://github.com/dhall-lang/dhall-haskell/pull/1415)++1.26.1++* TECHNICALLY BREAKING CHANGES: [Simplify `⫽` within projection](https://github.com/dhall-lang/dhall-haskell/pull/1283) / [Simplify nested record projections](https://github.com/dhall-lang/dhall-haskell/pull/1307)+    * These are technically breaking changes because you will need to update+      integrity checks that protect code simplified in this way+    * We're not bumping the major version since the likelihood that you're+      affected is quite low+* BUG FIX: [Fix performance regression](https://github.com/dhall-lang/dhall-haskell/pull/1335)+    * This change fixes the performance regression introduced in the previous+      release (version 1.26.0)+* BUG FIX: [Prevent REPL from inserting inferred `Sort`s into context](https://github.com/dhall-lang/dhall-haskell/pull/1318)+    * This protects the REPL from getting hosed if you define an expression+      using `:let` that has an inferred type of `Sort`+* NEW FEATURE: Improved `Inject`/`Interpret` support for 1-field constructors - ([#1315](https://github.com/dhall-lang/dhall-haskell/pull/1315) / [#1321](https://github.com/dhall-lang/dhall-haskell/pull/1321))+    * This adds a new `singletonConstructors` field to `InterpretOptions` that+      lets you control what Dhall type 1-field Haskell constructors correspond+      to+    * The default (`Wrapped`) is backwards compatible with the old behavior+    * The `Smart` option is probably what you want: it will strip the+      Haskell constructor from the Dhall type if the constructor has one+      anonymous field+    * The `Bare` option always strips 1-field Haskell constructors from the+      Dhall type+* NEW FEATURE: `--censor` flag that disables source code display ([#1312](https://github.com/dhall-lang/dhall-haskell/pull/1312) / [#1329](https://github.com/dhall-lang/dhall-haskell/pull/1329))+    * Use this flag when you don't want sensitive `Text` literals showing up in+      parsing or type-checking error messages+* [Format record fields more compactly if they fit on 1 line](https://github.com/dhall-lang/dhall-haskell/pull/1314)+    * The formatter will now format record fields on a field-by-field basis to+      avoid unnecessary vertical sprawl of formatted records+    * Specifically, record fields that fit on one line will now be formatted+      on one line+* [Add `--quiet` option to `dhall type`](https://github.com/dhall-lang/dhall-haskell/pull/1325)+    * This lets you use `dhall type` in "check only" mode (e.g. for CI for+      for development feedback)+* Improved GHCJS support - ([#1311](https://github.com/dhall-lang/dhall-haskell/pull/1311) / [#1330](https://github.com/dhall-lang/dhall-haskell/pull/1330))+* [Fix all executables to accept `--version`](https://github.com/dhall-lang/dhall-haskell/pull/1334)+    * Note that the `dhall version` subcommand is still supported, too+* [New `Dhall.Version` module](https://github.com/dhall-lang/dhall-haskell/pull/1332)+* [Don't normalize inferred types](https://github.com/dhall-lang/dhall-haskell/pull/1317)+    * This fixes `dhall type` to more accurately follow the standard+* [Initial changes for GHC 8.8 support](https://github.com/dhall-lang/dhall-haskell/pull/1324)+* [Fix Haddock formatting for `dhallFromJSON`](https://github.com/dhall-lang/dhall-haskell/pull/1316)+* [Improved Windows caching support](https://github.com/dhall-lang/dhall-haskell/pull/1272)+    * `dhall` will now prefer the `%LOCALAPPDATA%` directory for caching if it is+      available+* [Warn about missing cache directories](https://github.com/dhall-lang/dhall-haskell/pull/1320)++1.26.0++* [Supports version 10.0.0 of the standard](https://github.com/dhall-lang/dhall-lang/releases/tag/v10.0.0)+* BREAKING CHANGE TO THE LANGUAGE: [Remove old union literal syntax](https://github.com/dhall-lang/dhall-haskell/pull/1176)+    * Union literals of the form `< x = e | ... >` are no longer valid+    * For more details, see: [Migration: Deprecation of old union literal syntax](https://github.com/dhall-lang/dhall-lang/wiki/Migration%3A-Deprecation-of-old-union-literal-syntax)+    * Also see the [changelog for standard version 10.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v10.0.0) for more details+* BREAKING CHANGE TO THE API: [Change `X` to be a type synonym for `Data.Void`](https://github.com/dhall-lang/dhall-haskell/pull/1172)+    * This is a breaking change if you were previously pattern matching on the+      `X` constructor.  You can replace that with the use of `Data.Void.absurd`+* BREAKING CHANGE TO THE API: [Treat multi-`let`s as syntactic sugar](https://github.com/dhall-lang/dhall-haskell/pull/1242)+    * This is a breaking change because the `Let` constructor now only stores+      one `Binding` instead of a `NonEmpty` list of `Binding`s+* PERFORMANCE REGRESSION & TECHNICALLY BREAKING CHANGE TO THE LANGUAGE: [Dependent types](https://github.com/dhall-lang/dhall-haskell/pull/1164)+    * You can now write functions from terms to types+    * There is also now language support for tests of the form+      `assert : x === y`+    * This deteriorates the performance of large multi-`let` expressions+      (See: [#1306](https://github.com/dhall-lang/dhall-haskell/issues/1306))+    * Splitting large multi-`let` expressions into smaller files may mitigate+      the problem as a work-around for now+    * Follow [#1129](https://github.com/dhall-lang/dhall-haskell/issues/1129)+      for work to fix this performance regression+    * This is also a technically breaking change because `assert` is now a+      reserved keyword+    * See the [changelog for standard version 10.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v10.0.0) for more details+* TECHNICALLY BREAKING CHANGE TO THE LANGUAGE: [Add `Natural/subtract` built-in](https://github.com/dhall-lang/dhall-haskell/pull/1133)+    * The language now supports machine subtraction, which can be used to+      support several other high-performance operations (like `Natural`+      comparisons)+    * This is a technically breaking change if you used `Natural/subtract` as an+      identifier in your code+    * See the [changelog for standard version 10.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v10.0.0) for more details+* TECHNICALLY BREAKING CHANGE TO THE LANGUAGE: [More simplifications for field selection](https://github.com/dhall-lang/dhall-haskell/pull/1174)+    * Now the interpreter will more intelligently simplify certain field+      projections+    * For example: `λ(x : { a : Bool, b : Bool }) → (x ⫽ { c = 0 }).{ a, c }.c`+      will now simplify to `λ(x : { a : Bool, b : Bool }) → 0 `+    * This is a technically breaking change because you will need to update+      integrity checks that protect code simplified in this way+    * See the [changelog for standard version 10.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v10.0.0) for more details+* TECHNICALLY BREAKING CHANGE TO THE LANGUAGE: [Simplify `⫽` when its arguments are equivalent](https://github.com/dhall-lang/dhall-haskell/pull/1196)+    * This is a technically breaking change for the same reason: this will+      perturb semantic integrity checks for affected code+    * See the [changelog for standard version 10.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v10.0.0) for more details+* NEW FEATURE: [Restore support for records containing both types and terms](https://github.com/dhall-lang/dhall-haskell/pull/1173)+    * In other words `{ foo = 1, bar = Bool }` is now valid again+    * This means that you now can export a single package containing both types+      and terms+    * See the [changelog for standard version 10.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v10.0.0) for more details+* [`dhall format` now preserves `let` comments](https://github.com/dhall-lang/dhall-haskell/pull/1273)+    * `dhall` format will now preserve comments in the following locations of+      a `let` binding:+    * `let {- HERE -} x {- HERE -} : {- HERE -} Bool = {- HERE -} True in x`+    * This support handles both single-line and multi-line comments and also+      takes care of correctly indenting/dedenting them+    * Note that comments before the `let` keyword are still not preserved+      (unless it is the beginning of the file)+* [Add API support for marshalling recursive types](https://github.com/dhall-lang/dhall-haskell/pull/1195)+    * You can now marshal recursive types from Dhall into Haskell using the+      newly-added utilities+    * See also: [#1298](https://github.com/dhall-lang/dhall-haskell/pull/1298)+* [New `:help` command for `dhall repl`](https://github.com/dhall-lang/dhall-haskell/pull/1237)+* New `--no-cache` flag [#1290](https://github.com/dhall-lang/dhall-haskell/pull/1290) / [#1434](https://github.com/dhall-lang/dhall-haskell/pull/1434) / [#1436](https://github.com/dhall-lang/dhall-haskell/pull/1436)+    * You can now disable use of the cache with this flag+    * This comes in handy if you want to disable α-normalization for imports+      protected by a semantic integrity check+* Bug fixes+    * [Fix `isNormalized` for field selections](https://github.com/dhall-lang/dhall-haskell/pull/1210)+    * [Simplify `Natural/subtract` when its arguments are equivalent](https://github.com/dhall-lang/dhall-haskell/pull/1220)+    * [Fix `NaN` to be judgmentally equivalent to itself](https://github.com/dhall-lang/dhall-haskell/pull/1231)+    * [Fix `Inject` instance for lists](https://github.com/dhall-lang/dhall-haskell/pull/1261)+    * [Fix typechecking of `toMap`](https://github.com/dhall-lang/dhall-haskell/pull/1279)+* Performance optimizations+    * [Optimize a few `Set` instances](https://github.com/dhall-lang/dhall-haskell/pull/1184)+    * [Remove some redundant sorting during normalization](https://github.com/dhall-lang/dhall-haskell/pull/1228)+* Improvements to error messages+    * [Improve error reporting for failed remote imports](https://github.com/dhall-lang/dhall-haskell/pull/1188)+    * [Improve HTTP errors](https://github.com/dhall-lang/dhall-haskell/pull/1253)+* Improvements to formatting+    * [Indent function arguments when formatting](https://github.com/dhall-lang/dhall-haskell/pull/1167)+    * [Prefer unquoted URLs](https://github.com/dhall-lang/dhall-haskell/pull/1235)+    * [Strip leading whitespace](https://github.com/dhall-lang/dhall-haskell/pull/1270)+* Improvements to diffs+    * [Fix diffs for lists](https://github.com/dhall-lang/dhall-haskell/pull/1213)+    * [Improve diff for non-empty lists](https://github.com/dhall-lang/dhall-haskell/pull/1244)+    * [Small fixes to `dhall diff`](https://github.com/dhall-lang/dhall-haskell/pull/1263)+* Improvements to documentation+    * [Fix documentation for `UnionInputType`](https://github.com/dhall-lang/dhall-haskell/pull/1230)+    * [Document support for caching protected imports](https://github.com/dhall-lang/dhall-haskell/pull/1247)+* Improvements to command-line interface+    * [Improve description of `dhall lint`](https://github.com/dhall-lang/dhall-haskell/pull/1264)+    * [Change `dhall type` to resolve imports](https://github.com/dhall-lang/dhall-haskell/pull/1281)++1.25.0++* Supports version 9.0.0 of the standard+    * See: https://github.com/dhall-lang/dhall-lang/releases/tag/v9.0.0+* BREAKING CHANGE: Remove support for old-style `List`-like `Optional` literals+    * List-like `Optional` Literals (i.e. `[ 1 ] : Optional Natural`) are no+      longer valid+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1002+* BREAKING CHANGE: Add support for semi-semantic caching+    * This change significantly improves the performance of imports+    * This change also automatically caches imports without an integrity check+    * This changes several types in `Dhall.Import` to support this new+      feature+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1113+* BREAKING CHANGE: Implement new Unicode braced escape sequence+    * Escape sequences encoding surrogate pairs are no longer valid+    * Instead, characters previously encoded as surrogate pairs can instead be+      encoded as a braced sequence+    * For example: "\uD834\uDD1E" must now be written as "\u{1D11E}"+    * See: https://github.com/dhall-lang/dhall-haskell/pull/987+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1104+* BREAKING CHANGE: Make the type of extract richer:+    * `Dhall.extract` can now return a detailed error instead of just a `Maybe`+    * This is a breaking chnage because the type of `extract` changed+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1011+* BREAKING CHANGE: Add support for importing expressions `as Location`+    * This is a breaking change because a new `Location` constructor was added+      to `ImportMode`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1019+* BREAKING CHANGE: Switch `Var` to use an `Int`+    * This is a performance improvement, but also a breaking change since the+      `Integer` in the `Var` constructor was changed to an `Int`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1044+* BREAKING CHANGE: Add new `toMap` keyword+    * This is a breaking change to the API because a new `ToMap` constructor+      was added to the `Expr` type+    * This is also a technically breaking change to the language because `toMap`+      is now a reserved keyword, although most code should be unaffected in+      practice+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1041+* BREAKING CHANGE: Sort the fields of a record projection during normalization+    * This is a technically breaking change to the language because any+      expressions with an uninterpreted record projection will have a different+      semantic integrity check.  However, most could should be unaffected in+      practice+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1111+* BUG FIX: Fix substitution into record projection by type+    * An expression like this one was being incorrectly rejected:+      `let e = { a = 10, b = "Text" } let s = { a : Natural } in e.(s)`, which+      this change fixes+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1012+* BUG FIX: Reject record projection when there is a field type mismatch+    * Record projection by type was previously not checking the expected+      field types, which this change fixes+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1027+* BUG FIX: Fix linting of unused let bindings+    * Certain let bindings were not correctly detected as unused, which this+      change fixes+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1001+* BUG FIX: Fix `--file` option+    * The `--file` option from the previous release did not work, due to not+      computing relative paths correctly, which this change fixes+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1004+* BUG FIX: Minor fix to `dhall diff`+    * `dhall diff` was incorrectly displaying spurious differences for+      identical lists that were function arguments, which this change fixes+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1006+* BUG FIX: Allow `Sort` as type annotation+    * This should have been implemented in the previous release as part of+      supporting version 8.0.0 of the standard, but was missed+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1024+* BUG FIX: `Dhall.Map`: Reflect original key ordering in `Ord` instance+    * `Dhall.Map` now considers key order when comparing `Map`s, which it should+      have done before, but didn't+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1050+* BUG FIX: Consistently format multi-line strings+    * The formatter now formats naked multi-line strings the same as nested+      multi-line strings+    * Specifically, naked multi-line strings can now be formatted on a single+      (just like nested multi-line strings)+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1056+* BUG FIX: Make `isNormalized` consistent with `normalize`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1115+* BUG FIX: Make `normalizeWithM` consistent with `normalize`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1126+* BUG FIX: Fix import alternatives to recover from type errors+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1152+* Feature: Semi-semantic caching+    * The Haskell implementation now implicitly caches *all* local imports, not+      just imports frozen by integrity checks, so that you don't have to freeze+      them when doing local development+    * These cached imports are still correctly invalidated if they or any of+      their dependencies change+    * This new implicit cache is stored underneath `~/.cache/dhall-haskell` by+      default+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1154+* Feature: New `dhall text` subcommand+    * This new subcommand supersedes the old `dhall-to-text` executable+* Feature: Add `instance Lift (Expr s a)`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1119+* Fixes and improvements to error messages:+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1030+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1137+* Fixes and improvements to tests:+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1155+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1159+* Performance improvements+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1036+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1051+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1048+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1057+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1065+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1066+    * See: https://github.com/dhall-lang/dhall-haskell/pull/1085++1.24.0++* Supports version 8.0.0 of the standard+    * See: https://github.com/dhall-lang/dhall-lang/releases/tag/v8.0.0+* BREAKING CHANGE: Allow tabs and blank lines in multi-line strings+    * Blank lines are now ignored for the purpose of dedenting multiline strings+    * Lines with leading tabs (or mixed tabs and spaces) are now dedented, too,+      so long as they all share the same prefix+    * This is technically a breaking change, but unlikely to affect programs+      in practice, especially if they were formatted with `dhall format`.  This+      change mainly affects programs that were not indented correctly.+    * See the changelog for standard version 8.0.0 for more details+* BREAKING CHANGE: Simplify bare interpolations+    * Expressions like `λ(x : Text) → "${x}"` now simplify to `λ(x : Text) → x`+    * This is a technically breaking change because it changes how these sorts+      of expressions are serialized.  This does not affect semantic integrity+      checks and the new simplified expressions are extensionally equivalent to+      their older counterpart expressions.+    * See the changelog for standard version 8.0.0 for more details+* BREAKING CHANGE: Encode integrity check as multihash+    * Semantic integrity checks are now encoded using the multihash spec+    * This is a technically breaking change that does not perturb the hash for+      user-facing semantic integrity checks.  This only affects how expressions+      with unresolved imports are serialized, but semantic integrity checks are+      only computed for fully-resolved imports.+    * See the changelog for standard version 8.0.0 for more details+* BUG FIX: Fix type-checker to reject invalid record type annotations+    * e.g. `{ x = 1 } : { x : Text }` was not properly rejected by the type+      checker+    * See: https://github.com/dhall-lang/dhall-haskell/pull/965+* BUG FIX: Custom header forwarding fixed+    * Forwarding custom headers could previously fail in various ways, such as:+        * Cyclic imports leading to endless network requests+        * Resolving a non-existent import for the custom headers+        * Resolving an existing but incorrect import for the custom headers+    * This change fixes that by forwarding custom headers by value instead of+      by reference+    * See: https://github.com/dhall-lang/dhall-haskell/pull/967+* BUG FIX: Fix GHCJS support+    * `Natural/fold` was broken in version 1.22, which this change fixes+    * Specifically, it would hang for `Natural` numbers greater than 1+    * See: https://github.com/dhall-lang/dhall-haskell/pull/985+* BUG FIX: `dhall diff` no longer double-prints key-value separators+    * See: https://github.com/dhall-lang/dhall-haskell/pull/952+* Feature: Record projection by expression+    * You can now project out a subset of record fields by the expected type+    * `let t = { x : Natural } let p = { x = 1, y = 2 } in p.(t) = { x = 1 }`+    * See the changelog for standard version 8.0.0 for more details+* Feature: Inline headers+    * You no longer need to specify custom headers in a separate import.  You+      can now specify them inline within the same file.+    * e.g.: `https://example.com/x using [ { header = "Foo", value = "Bar" } ]`+    * See the changelog for standard version 8.0.0 for more details+* Feature: Allow `Sort` as a type annotation+    * An expression such as `Kind → Kind : Sort` will now type-check+    * `Sort` is still disallowed outside of a type annotation+    * See the changelog for standard version 8.0.0 for more details+* Feature: Allow self-describe-cbor when decoding+    * Dhall expressions serialized as CBOR can be tagged to describe themselves+      as CBOR without affecting decoding+    * See the changelog for standard version 8.0.0 for more details+* Feature: New `--file` option for `dhall` commands+    * In other words, instead of `dhall <<< './some/file` you can now use+      `dhall --file some/file`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/949+* Feature: New `--cache` flag for `dhall freeze` command+    * This automates the idiom used by the Prelude to optimistically cache+      imports but gracefully degrade if the semantic integrity check fails+    * See: https://github.com/dhall-lang/dhall-haskell/pull/980+* Feature: Add `:clear` command to `dhall repl`+    * This deletes previous bindings from the history so that they can be+      garbage collected+    * See: https://github.com/dhall-lang/dhall-haskell/pull/966+* Feature: New `chunkExprs` `Traversal` added to `Dhall.Core`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/954+* Feature: New `Dhall.Optics` module+    * This re-exports some convenient @lens@ utilities used internally for+      packages trying to avoid a @lens@ dependency+    * See: https://github.com/dhall-lang/dhall-haskell/pull/986+* More GHC 8.8 support+    * See: https://github.com/dhall-lang/dhall-haskell/pull/961++1.23.0++* BREAKING CHANGE: Fix marshaling union literals+    * 1.22.0 introduced two separate bugs in marshaling union literals between+      Dhall and Haskell, which this release fixes:+        * Dhall enums did not correctly map onto Haskell enums+        * New-style union literals (i.e. `< A : T >.A x`) were not correctly+          supported+    * See: https://github.com/dhall-lang/dhall-haskell/pull/918+    * See: https://github.com/dhall-lang/dhall-haskell/pull/927+    * See: https://github.com/dhall-lang/dhall-haskell/pull/936+* BUG FIX: Fix α-normalization+    * Version 1.22.0 introduced a new faster evaluation algorithm, but the new+      algorithm introduced two α-normalization regression, which this release+      fixes+    * The primary effect of this bug was that semantic integrity checks would+      fail for expressions that contain an `if`/`then`/else` expression in their+      normal form+    * See: https://github.com/dhall-lang/dhall-haskell/pull/931+    * See: https://github.com/dhall-lang/dhall-haskell/pull/938+* BUG FIX: Fix merging of sort-level record types+    * The language standard requires that `{ a : Kind } ⩓ { b : Kind }` is+      valid, which this change fixes+    * See: https://github.com/dhall-lang/dhall-haskell/pull/891+* BUG FIX: `dhall freeze` respects the `--ascii` flag+    * See: https://github.com/dhall-lang/dhall-haskell/pull/934+* BUG FIX: Don't autocomplete fields for record types+    * This prevents the REPL from expanding `{ x : T }.<TAB>` to `{ x : T }.x`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/937+* Support `MonadFail`-related changes in GHC 8.8+    * See: https://github.com/dhall-lang/dhall-haskell/pull/912+* Add `cross` flag to simplify cross-compilation+    * This allows the `dhall` package to be built without using+      `TemplateHaskell`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/928+* Increase lines of context for error messages+    * Error messages now provide at least 20 lines of context instead of 3+      before truncating large expressions+    * See: https://github.com/dhall-lang/dhall-haskell/pull/916+* Add line numbers to error messages+    * The bottom of every Dhall type error includes the original source code,+      which now has line numbers on the left margin+    * See: https://github.com/dhall-lang/dhall-haskell/pull/919+* Expand lower bounds on `megaparsec`/`transformers-compat` dependencies+    * This is to support `dhall` on Debian Sid+    * See: https://github.com/dhall-lang/dhall-haskell/pull/939++1.22.0++* Supports version 7.0.0 of the standard+    * See: https://github.com/dhall-lang/dhall-lang/releases/tag/v7.0.0+* BREAKING CHANGE: Add support for empty alternatives+    * The `Union` type now has an optional (`Maybe`) type for each alternative+    * See the changelog for standard version 7.0.0 for more details+    * See: https://github.com/dhall-lang/dhall-haskell/pull/863+* BREAKING CHANGE: Remove support for URL fragments+    * The `URL` type no longer has a field for a URL fragment since the language+      no longer supports fragments+    * See the changelog for standard version 7.0.0 for more details+    * See: https://github.com/dhall-lang/dhall-haskell/pull/851+* BREAKING CHANGE: Remove deprecated `Path` type synonym+    * See: https://github.com/dhall-lang/dhall-haskell/pull/858+* BUG FIX: Correctly parse identifiers beginning with `http`+    * i.e. `httpPort` was supposed to be a valid identifier name and now is+    * See: https://github.com/dhall-lang/dhall-haskell/pull/870+* BUG FIX: Fix `dhall encode` bug+    * `dhall encode` bug was generating binary expressions that were valid+      (i.e. they would decode correctly) but were non-standard (i.e. hashing+      them would not match the hash you would normally get from a semantic+      integrity check)+    * Semantic integrity checks were not affected by this bug since they used+      a slightly different code path that generated the correct binary input to+      the hash.  Only the `dhall decode` subcommand was affected+    * See: https://github.com/dhall-lang/dhall-haskell/pull/859+* BUG FIX: Fix for `Dhall.UnionType`+    * This fixes some expressions that would previously fail to marshal into+      Haskell, specifically those were the marshalling logic was built using+      the `UnionType` utilities+    * See: https://github.com/dhall-lang/dhall-haskell/pull/857+* Feature: New `--alpha` flag to α-normalize command-line output+    * See: https://github.com/dhall-lang/dhall-haskell/pull/855+* Performance improvements+    * The normalizer is now *much* faster+    * See: https://github.com/dhall-lang/dhall-haskell/pull/876++1.21.0++* Supports version 6.0.0 of the language standard+    * See: https://github.com/dhall-lang/dhall-lang/releases/tag/v6.0.0+* BREAKING CHANGE: Remove the `constructors` keyword+    * ... as standardized in version 6.0.0 of the language standard+    * The deprecation cycle is over, so the keyword is no longer supported+    * For more details, see: https://github.com/dhall-lang/dhall-lang/wiki/Migration%3A-Deprecation-of-constructors-keyword+    * See: https://github.com/dhall-lang/dhall-haskell/pull/829+* BREAKING CHANGE: CBOR-encode only special `Double`s as half-floats+    * ... as standardized in version 6.0.0 of the language standard+    * CBOR `Double`s except `Infinity`/`-Infinity`/`NaN`/`0.0` are now encoded in at+      least 32 bits+    * See: https://github.com/dhall-lang/dhall-haskell/pull/822+* BREAKING CHANGE: Sort record and union fields when CBOR-encoding+    * Fields and alternatives are now sorted when serialized+    * This does not affect semantic integrity checks, which already sorted these+      fields/alternatives before hashing expressions+    * This does affect the serialization of expressions that have not been+      normalized (e.g. uninterpreted expressions transmitted over the wire)+    * See: https://github.com/dhall-lang/dhall-haskell/pull/835+* BUG FIX: Fix non-exhaustive pattern match in `dhall lint`+    * This fixes: `Irrefutable pattern failed for pattern Let (l' :| ls') d'`+    * This bug would cause `dhall lint` to fail on some nested `let`/`in`+      expressions+    * See: https://github.com/dhall-lang/dhall-haskell/pull/780+    * See: https://github.com/dhall-lang/dhall-haskell/pull/784+* BUG FIX: Don't fail if `$HOME` environment variable is unset+    * The interpreter was incorrectly throwing an exception if `HOME` was unset+    * The standard requires that implementations should handle the `HOME`+      environment variable being missing+    * See: https://github.com/dhall-lang/dhall-haskell/pull/789+* Feature: Remove version tag from semantic integrity check+    * ... as standardized in version 6.0.0 of the language standard+    * This is not a breaking change because this change also includes+      backwards-compatible support for semantic integrity checks produced by+      older versions of the interpreter+* Feature: Support Unicode path components+    * ... as standardized in version 6.0.0 of the language standard+    * You can now use Unicode in path components if they are quoted+    * i.e. `./families/"禺.dhall"` is now legal+* Feature: Add `Text/show` built-in+    * ... as standardized in version 6.0.0 of the language standard+    * You can now convert a `Text` literal to its equivalent Dhall source code+      (which is itself a `Text` literal)+    * This comes in handy when using Dhall code to generate JSON or Dhall code+    * See: https://github.com/dhall-lang/dhall-haskell/pull/811+* Feature: Add `--immediate-dependencies`/`--transitive-dependencies` flags for+  `dhall resolve`+    * You can now retrieve all of your immediate or transitive dependencies as a+      textual list+    * This simplifies integration with other command-line tools (such as file+      watchers)+    * See: https://github.com/dhall-lang/dhall-haskell/pull/795+    * See: https://github.com/dhall-lang/dhall-haskell/pull/803+* Feature: `dhall freeze` now only freezes remote imports by default+    * `dhall freeze` used to freeze all imports (including local imports and+      environment variables)+    * Now `dhall freeze` only freezes remote imports by default, which is what+      most users want+    * You can install freeze all imports using the `--all` flag+    * See: https://github.com/dhall-lang/dhall-haskell/pull/808+* Feature: `:save` and `:load` REPL state+    * `:save` with no arguments now saves the REPL state to a `.dhall-repl-N`+       file+    * The file format is a list of `dhall repl` commands+    * You can use `:load` to load the saved state back into the REPL+    * See: https://github.com/dhall-lang/dhall-haskell/pull/807+* Feature: Add `:hash` command to `dhall repl`+    * This lets you conveniently hash expressions within the `dhall repl`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/806+* Feature: Add `--check` flag to `dhall format`+    * Use this to check if the input is already formatted+    * Useful for continuous integration when you want to ensure that all code+      under version control remains formatted+    * See: https://github.com/dhall-lang/dhall-haskell/pull/810+* Feature: Add  `UnionInputType` builder for `InputType`s+    * This is the union analog of `RecordInputType`, letting you build a+      record explicitly instead of deriving the instance using GHC generics+    * See: https://github.com/dhall-lang/dhall-haskell/pull/775+* Feature: Add `:set`/`:unset` commands to `dhall repl`+    * You can use these commands to set or unset command-line options+    * Currently only setting/unsetting `--explain` is supported+* Standards-compliance fixes:+    * See: https://github.com/dhall-lang/dhall-haskell/pull/779+    * See: https://github.com/dhall-lang/dhall-haskell/pull/804+    * See: https://github.com/dhall-lang/dhall-haskell/pull/833+* Documentation fixes:+    * See: https://github.com/dhall-lang/dhall-haskell/pull/792+    * See: https://github.com/dhall-lang/dhall-haskell/pull/825+* Test fixes:+    * See: https://github.com/dhall-lang/dhall-haskell/pull/782+    * See: https://github.com/dhall-lang/dhall-haskell/pull/836+* Improved error messages:+    * See: https://github.com/dhall-lang/dhall-haskell/pull/812+    * See: https://github.com/dhall-lang/dhall-haskell/pull/815+    * See: https://github.com/dhall-lang/dhall-haskell/pull/824+* Formatting fixes:+    * See: https://github.com/dhall-lang/dhall-haskell/pull/831+* REPL fixes:+    * See: https://github.com/dhall-lang/dhall-haskell/pull/837++1.20.1++* BUG FIX: Fix binary encoding to use correct standard version+    * This fixes computed hashes to correctly match standard version 5.0.0+    * This is not marked as a breaking change since it is a bug fix.  The+      1.20.0 release will be blacklisted on Hackage and users should upgrade+      from 1.19.* directly to 1.20.1+    * See: https://github.com/dhall-lang/dhall-haskell/pull/771++1.20.0++* Supports version 5.0.0 of the language standard+    * See: https://github.com/dhall-lang/dhall-lang/releases/tag/v5.0.0+* BREAKING CHANGE TO THE LANGUAGE: Implement standardized support for multi-line+  literals+    * This updates the multi-line support to match the standard+    * This is a breaking change because empty lines within the multi-line+      literal now require leading whitespace whereas previously they did not+    * This is also a breaking change because now a newline is required after+      the opening `''` quotes whereas previously it was not required+    * If you use `dhall format` then your multi-line literals already have the+      necessary leading whitespace+* BREAKING CHANGE TO THE LANGUAGE: `constructors x = x`+    * Now the `constructors` keyword behaves like an identity function, since+      constructors can already be accessed as fields off the original union+      type.+    * This is a breaking change since any record of terms that contains a+      `constructors` field will now be a forbidden mixed record of types and+      terms.+    * This is also a breaking change if you annotated the type of what used to+      be a `constructors` record.+    * `dhall lint` will now remove the obsolete `constructors` keyword for you+    * See: https://github.com/dhall-lang/dhall-haskell/pull/693+    * See: https://github.com/dhall-lang/dhall-haskell/pull/701+* BREAKING CHANGE TO THE API: Restore `Parent` constructor for `Local` type+    * This more closely matches the standard and also enables `dhall format` to+      produce a leading `../` for imports instead of `./../`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/718+* BUG FIX: Fix type-checking bug for unions+    * The first fix was that the inferred type was wrong for unions where+      alternatives were types or kinds+    * The second fix was that unions that mixed terms/types/kinds were not+      properly rejected+    * See: https://github.com/dhall-lang/dhall-haskell/pull/763+* BUG FIX: Change how `dhall repl` handles prior definitions+    * This changes the REPL to handle previous bindings as if they were+      defined using a large `let` expression instead of adding them to the+      context+    * This fixes some type-checking false negatives+    * See: https://github.com/dhall-lang/dhall-haskell/pull/729+* Feature: Autocomplete for `dhall repl`+    * You can now auto-complete record fields, union constructors, and+      identifiers that are in scope+    * See: https://github.com/dhall-lang/dhall-haskell/pull/727+* Feature: GHCJS support+    * `dhall` can now be built using GHCJS, although some features are still+      not supported for GHCJS, such as:+        * Semantic integrity checks+        * Custom HTTP headers+    * Also, HTTP imports only work for URLs that support CORS+    * See: https://github.com/dhall-lang/dhall-haskell/pull/739+* Feature: Add support for records of records of types+    * You can now nest records of types+    * See: https://github.com/dhall-lang/dhall-haskell/pull/700+* Feature: Add `:quit` command for `dhall repl`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/719+* Feature: Add `--json` flag for `dhall {encode,decode}`+    * You can now produce/consume CBOR expressions via JSON instead of binary+    * See: https://github.com/dhall-lang/dhall-haskell/pull/717+* Feature: Add decoding logic for `as Text`+    * You can now preserve the `as Text` qualifier on imports when serializing+      them+    * See: https://github.com/dhall-lang/dhall-haskell/pull/712+* Prenormalize substituted expressions+    * This is a performance improvement that reduces the time and memory+      consumption when normalizing expressions+    * See: https://github.com/dhall-lang/dhall-haskell/pull/765++1.19.1+++* BUG FIX: Fix serious `dhall lint` bug+    * `dhall lint` would sometimes remove `let` expressions that were still+      in use+    * See: https://github.com/dhall-lang/dhall-haskell/pull/703+* BUG FIX: Fix import caching efficiency bug+    * Some imports were being wastefully fetched multiple times+    * See: https://github.com/dhall-lang/dhall-haskell/pull/702+* Feature: Generate dot graph to visualize import graph+    * Use the `dhall resolve --dot` command+    * See: https://github.com/dhall-lang/dhall-haskell/pull/698+    * See: https://github.com/dhall-lang/dhall-haskell/pull/713+* Improve HTTP error messages+    * See: https://github.com/dhall-lang/dhall-haskell/pull/710++1.19.0++* Supports version 4.0.0 of the language standard+    * See: https://github.com/dhall-lang/dhall-lang/releases/tag/v4.0.0+* BREAKING CHANGE TO THE LANGUAGE AND API: Prevent Hurkens' paradox+    * This fixes a type-checking soundness bug which permitted infinite loops+    * This is a breaking change because infinite loops are no longer possible+    * This is also a breaking change because a record of types is now treated as+      a kind instead of a type+    * See: https://github.com/dhall-lang/dhall-haskell/pull/680+* BREAKING CHANGE TO THE LANGUAGE AND API: `Double`s are now double-precision+  floating point numbers+    * This restricts the range of `Double`s to IEEE 754 double-precision+      floating point+    * This also implies that you can no longer convert `Scientific` values to+      `Dhall` expressions (i.e. no `Inject` instance for `Scientific`)+    * See: https://github.com/dhall-lang/dhall-haskell/pull/667+* BREAKING CHANGE TO THE API: Preserve field order for record projection+    * The API uses a new `Dhall.Set.Set` type instead of `Data.Set.Set`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/670+* BREAKING CHANGE TO THE API: Add support for multi-`let` expressions+    * This changes the `Let` constructor to now support storing multiple+      bindings per `let` expression+    * See: https://github.com/dhall-lang/dhall-haskell/pull/675+* Access constructors as if they were fields of the union type+    * In other words: `< Left : Bool | Right : Natural >.Left`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/657+* Support GHC 8.6+    * See: https://github.com/dhall-lang/dhall-haskell/pull/669+* Add support for quoted path components+    * i.e. `/"foo"/bar/"baz qux"` or `https://example.com/foo/"bar?baz"?qux`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/690+* Fix parsing of `//\\` operator+    * See: https://github.com/dhall-lang/dhall-haskell/commit/9d0fd42d95ab69fa64da4afd8b60d69aca8e65a6+* Preserve Unicode characters when formatting code+    * See: https://github.com/dhall-lang/dhall-haskell/pull/679+* Allow identifier names to begin with `Some`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/658+* Add `subExpressions` `Traversal`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/660+* Add `normalizeWithM` for monadic normalization+    * See: https://github.com/dhall-lang/dhall-haskell/pull/371+* Custom normalizers now take precedence over default normalization logic+    * This allows one to override the implementation of built-in operators+    * See: https://github.com/dhall-lang/dhall-haskell/pull/684++1.18.0++* Supports version 3.0.0 of the language standard:+    * See: https://github.com/dhall-lang/dhall-lang/releases/tag/v3.0.0+* BREAKING CHANGE TO THE LANGUAGE AND API: New `Some`/`None` constructors for+  `Optional` values+    * Example: `[ Some 1, None Natural ]`+    * This is a breaking change to the language because `Some` and `None` are+      now reserved keywords+    * This is a breaking change to the API because `Some` and `None` are new+      constructors for the `Expr` type+* BREAKING CHANGE TO THE LANGUAGE AND API: Support for kind polymorphism+    * This adds a new `Sort` constant above `Kind` in the hierarchy+    * i.e. `Type : Kind : Sort`+    * This is a breaking change to the language because `Sort` is now a+      reserved keyword+    * This is a breaking change to the API because `Sort` is a new+      constructor for the `Expr` type+* BREAKING CHANGE TO THE API: New `Dhall.Map` module+    * This replaces `InsOrdHashMap` in the API+    * The primary motivation is to improve performance and to remove the+      dependency on `insert-ordered-containers`+* BREAKING CHANGE TO THE API: Use standard version instead of protocol version+    * The binary protocol is now versioned alongside the standard+    * The `ProtocolVersion` type is renamed to `StandardVersion` and the+    * `--protocol-version` option is renamed to `--standard-version`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/634+* BUG FIX: Fix import chaining for custom header imports+    * See: https://github.com/dhall-lang/dhall-haskell/pull/618+* BUG FIX: Fix import chaining for imports protected by semantic integrity+  checks+    * See: https://github.com/dhall-lang/dhall-haskell/pull/584+* BUG FIX: Record literals and types produced by `∧`/`⫽`/`⩓` are now sorted+    * This ensures that β-normalization is idempotent+    * See: https://github.com/dhall-lang/dhall-haskell/pull/572+* BUG FIX: `dhall freeze` now correctly handles the starting file being+  located outside the current working directory+    * See: https://github.com/dhall-lang/dhall-haskell/commit/a22aa79d1957be9ecf166ea066e2a9a5b309e1ae+* BUG FIX: Fix parsing of IPv4-mapped IPv6 addresses+    * See: https://github.com/dhall-lang/dhall-haskell/pull/632+* FEATURE: New `--ascii` flag for ASCII output+    * See: https://github.com/dhall-lang/dhall-haskell/pull/570+* FEATURE: New `dhall encode` and `dhall decode` subcommands+    * These allow you to transform Dhall source code to and from its binary+      representation+    * See: https://github.com/dhall-lang/dhall-haskell/pull/588+* LARGE parsing performance improvements+    * Parsing is about 10x-100x faster on most code+    * See: https://github.com/dhall-lang/dhall-haskell/pull/591+    * See: https://github.com/dhall-lang/dhall-haskell/pull/592+    * See: https://github.com/dhall-lang/dhall-haskell/pull/597+    * See: https://github.com/dhall-lang/dhall-haskell/pull/601+    * See: https://github.com/dhall-lang/dhall-haskell/pull/602+    * See: https://github.com/dhall-lang/dhall-haskell/pull/604+    * See: https://github.com/dhall-lang/dhall-haskell/pull/606+* Type-checking performance improvements:+    * See: https://github.com/dhall-lang/dhall-haskell/pull/566+* Normalization performance improvements:+    * See: https://github.com/dhall-lang/dhall-haskell/pull/610+* `dhall freeze` now caches the imports as it freezes them+    * See: https://github.com/dhall-lang/dhall-haskell/pull/587+* `dhall freeze` now refreezes imports with invalid semantic integrity checks+    * See: https://github.com/dhall-lang/dhall-haskell/pull/637+* `dhall freeze` now adds a trailing newline+    * See: https://github.com/dhall-lang/dhall-haskell/pull/629+* Build against `megaparsec-7.0.*`+    * See: https://github.com/dhall-lang/dhall-haskell/pull/565+* Support GHC 8.6+    * See: https://github.com/dhall-lang/dhall-haskell/pull/599+    * See: https://github.com/dhall-lang/dhall-haskell/pull/623+* Support GHC all the way back to 7.10.3+    * See: https://github.com/dhall-lang/dhall-haskell/pull/595+    * See: https://github.com/dhall-lang/dhall-haskell/pull/621+* Improvements to error messages:+    * See: https://github.com/dhall-lang/dhall-haskell/pull/563+    * See: https://github.com/dhall-lang/dhall-haskell/pull/576+    * See: https://github.com/dhall-lang/dhall-haskell/pull/583+    * See: https://github.com/dhall-lang/dhall-haskell/pull/589+++1.17.0++* This release corresponds to version 2.0.0 of the language standard+* BREAKING CHANGE TO THE LANGUAGE AND API: Binary serialization support+    * This is a breaking change to the hash for all semantic integrity checks+    * The hash used by the semantic integrity check is now based on the+      binary representation instead of a text representation of the+      expression+    * You can pin the new hashes by supplying the `--protocol-version 1.0`+      option on the command line until you need support for newer language+      features     * This also includes a breaking change to `ImportType` in the API * BREAKING CHANGE TO THE LANGUAGE: Disallow combining records of terms and   types
LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) 2018 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,12 +1,12 @@ {-# LANGUAGE OverloadedStrings #-} module Main (main) where -import Criterion.Main (defaultMain)+import Data.Void        (Void)+import Test.Tasty.Bench -import qualified Criterion as Criterion-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  dhallPreludeImport :: Core.Import@@ -21,32 +21,52 @@     }   } -issue412 :: Core.Expr s TypeCheck.X -> Criterion.Benchmarkable-issue412 prelude = Criterion.whnf TypeCheck.typeOf expr+issue412 :: Core.Expr s Void -> Benchmarkable+issue412 prelude = whnf TypeCheck.typeOf expr   where     expr-      = Core.Let (pure (Core.Binding "prelude" Nothing prelude))+      = 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 -> Criterion.Benchmarkable-unionPerformance prelude = Criterion.whnf TypeCheck.typeOf expr+unionPerformance :: Core.Expr s Void -> Benchmarkable+unionPerformance prelude = whnf TypeCheck.typeOf expr   where-    innerBinding =-        Core.Binding "big" Nothing-            (prelude `Core.Field` "types" `Core.Field` "Big")--    outerBinding =-        Core.Binding "x" Nothing-            (Core.Let (pure innerBinding) (Core.Prefer "big" "big"))--    expr = Core.Let (pure outerBinding) "x"+    expr =+        Core.Let+            (Core.Binding+                Nothing+                "x"+                Nothing+                Nothing+                Nothing+                (Core.Let+                    (Core.Binding+                        Nothing+                        "big"+                        Nothing+                        Nothing+                        Nothing+                        (prelude `Core.Field` types `Core.Field` big)+                    )+                    (Core.Prefer mempty Core.PreferFromSource "big" "big")+                )+            )+            "x"+    types = Core.makeFieldSelection "types"+    big = Core.makeFieldSelection "Big"  main :: IO ()-main = do-  prelude <- Import.load (Core.Embed dhallPreludeImport)+main =   defaultMain-    [ Criterion.bench "issue 412" (issue412 prelude)-    , Criterion.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/deep-nested-large-record/prelude.dhall view
@@ -1,5 +1,5 @@ { types =-  { Big = constructors ./BigEnum.dhall-  , Little = constructors ./LittleEnum.dhall+  { Big = ./BigEnum.dhall+  , Little = ./LittleEnum.dhall   } }
− benchmark/dhall-command/Main.hs
@@ -1,20 +0,0 @@--{-# LANGUAGE OverloadedStrings #-}--module Main where--import qualified Dhall.Main as Main-import           Dhall.Binary (defaultStandardVersion)--options :: Main.Options-options = Main.Options-  { Main.mode = Main.Default Nothing False False-  , Main.explain = False-  , Main.plain = False-  , Main.ascii = False-  , Main.standardVersion = defaultStandardVersion-  }--main :: IO ()-main = do-  Main.command options
− benchmark/examples/issue108.dhall
@@ -1,61 +0,0 @@-λ(xs : List { cores : Natural, host : Text, key : Text, mandatoryFeatures : -List Text, platforms : List < AArch64_Linux : {} | ARMv5tel_Linux : {} | -ARMv7l_Linux : {} | I686_Cygwin : {} | I686_Linux : {} | MIPS64el_Linux : {} | -PowerPC_Linux : {} | X86_64_Cygwin : {} | X86_64_Darwin : {} | X86_64_FreeBSD : -{} | X86_64_Linux : {} | X86_64_Solaris : {} >, speedFactor : Natural, -supportedFeatures : List Text, user : Optional Text }) → List/fold { cores : -Natural, host : Text, key : Text, mandatoryFeatures : List Text, platforms : -List < AArch64_Linux : {} | ARMv5tel_Linux : {} | ARMv7l_Linux : {} | -I686_Cygwin : {} | I686_Linux : {} | MIPS64el_Linux : {} | PowerPC_Linux : {} | -X86_64_Cygwin : {} | X86_64_Darwin : {} | X86_64_FreeBSD : {} | X86_64_Linux : -{} | X86_64_Solaris : {} >, speedFactor : Natural, supportedFeatures : List -Text, user : Optional Text } xs Text (λ(x : { cores : Natural, host : Text, -key : Text, mandatoryFeatures : List Text, platforms : List < AArch64_Linux : -{} | ARMv5tel_Linux : {} | ARMv7l_Linux : {} | I686_Cygwin : {} | I686_Linux : -{} | MIPS64el_Linux : {} | PowerPC_Linux : {} | X86_64_Cygwin : {} | -X86_64_Darwin : {} | X86_64_FreeBSD : {} | X86_64_Linux : {} | X86_64_Solaris : -{} >, speedFactor : Natural, supportedFeatures : List Text, user : Optional -Text }) → λ(y : Text) → (Optional/fold Text x.user Text (λ(user : Text) -→ user ++ "@" ++ x.host ++ "") x.host ++ " " ++ (merge { Empty = λ(_ : {}) -→ "", NonEmpty = λ(result : Text) → result } (List/fold < AArch64_Linux : -{} | ARMv5tel_Linux : {} | ARMv7l_Linux : {} | I686_Cygwin : {} | I686_Linux : -{} | MIPS64el_Linux : {} | PowerPC_Linux : {} | X86_64_Cygwin : {} | -X86_64_Darwin : {} | X86_64_FreeBSD : {} | X86_64_Linux : {} | X86_64_Solaris : -{} > x.platforms < Empty : {} | NonEmpty : Text > (λ(element : < AArch64_Linux -: {} | ARMv5tel_Linux : {} | ARMv7l_Linux : {} | I686_Cygwin : {} | I686_Linux -: {} | MIPS64el_Linux : {} | PowerPC_Linux : {} | X86_64_Cygwin : {} | -X86_64_Darwin : {} | X86_64_FreeBSD : {} | X86_64_Linux : {} | X86_64_Solaris : -{} >) → λ(status : < Empty : {} | NonEmpty : Text >) → merge { Empty = -λ(_ : {}) → < NonEmpty = merge { AArch64_Linux = λ(_ : {}) → -"aarch64-linux", ARMv5tel_Linux = λ(_ : {}) → "armv5tel-linux", ARMv7l_Linux -= λ(_ : {}) → "armv7l-linux", I686_Cygwin = λ(_ : {}) → "i686-cygwin", -I686_Linux = λ(_ : {}) → "i686-linux", MIPS64el_Linux = λ(_ : {}) → -"mips64el-linux", PowerPC_Linux = λ(_ : {}) → "powerpc-linux", X86_64_Cygwin -= λ(_ : {}) → "x86_64-cygwin", X86_64_Darwin = λ(_ : {}) → -"x86_64-darwin", X86_64_FreeBSD = λ(_ : {}) → "x86_64-freebsd", X86_64_Linux -= λ(_ : {}) → "x86_64-linux", X86_64_Solaris = λ(_ : {}) → -"x86_64-solaris" } element | Empty : {} >, NonEmpty = λ(result : Text) → < -NonEmpty = (merge { AArch64_Linux = λ(_ : {}) → "aarch64-linux", -ARMv5tel_Linux = λ(_ : {}) → "armv5tel-linux", ARMv7l_Linux = λ(_ : {}) → -"armv7l-linux", I686_Cygwin = λ(_ : {}) → "i686-cygwin", I686_Linux = λ(_ : -{}) → "i686-linux", MIPS64el_Linux = λ(_ : {}) → "mips64el-linux", -PowerPC_Linux = λ(_ : {}) → "powerpc-linux", X86_64_Cygwin = λ(_ : {}) → -"x86_64-cygwin", X86_64_Darwin = λ(_ : {}) → "x86_64-darwin", X86_64_FreeBSD -= λ(_ : {}) → "x86_64-freebsd", X86_64_Linux = λ(_ : {}) → -"x86_64-linux", X86_64_Solaris = λ(_ : {}) → "x86_64-solaris" } element) ++ -"," ++ result | Empty : {} > } status : < Empty : {} | NonEmpty : Text >) < -Empty = {=} | NonEmpty : Text >) : Text) ++ " " ++ x.key ++ " " ++ Integer/show -(Natural/toInteger x.cores) ++ " " ++ Integer/show (Natural/toInteger -x.speedFactor) ++ " " ++ (merge { Empty = λ(_ : {}) → "", NonEmpty = -λ(result : Text) → result } (List/fold Text x.supportedFeatures < Empty : {} -| NonEmpty : Text > (λ(element : Text) → λ(status : < Empty : {} | NonEmpty -: Text >) → merge { Empty = λ(_ : {}) → < NonEmpty = element | Empty : {} ->, NonEmpty = λ(result : Text) → < NonEmpty = element ++ "," ++ result | -Empty : {} > } status : < Empty : {} | NonEmpty : Text >) < Empty = {=} | -NonEmpty : Text >) : Text) ++ " " ++ (merge { Empty = λ(_ : {}) → "", -NonEmpty = λ(result : Text) → result } (List/fold Text x.mandatoryFeatures < -Empty : {} | NonEmpty : Text > (λ(element : Text) → λ(status : < Empty : {} -| NonEmpty : Text >) → merge { Empty = λ(_ : {}) → < NonEmpty = element | -Empty : {} >, NonEmpty = λ(result : Text) → < NonEmpty = element ++ "," ++ -result | Empty : {} > } status : < Empty : {} | NonEmpty : Text >) < Empty = -{=} | NonEmpty : Text >) : Text) ++ "\n") ++ y) ""
− 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/map/Main.hs
@@ -1,44 +0,0 @@-{-# LANGUAGE BangPatterns     #-}-{-# LANGUAGE TypeApplications #-}--module Main where--import Criterion.Main (defaultMain, bgroup, bench, whnf, nfIO)--import qualified Criterion.Main as Criterion-import qualified Dhall.Map as Map--testData :: Integer -> Map.Map Integer Integer-testData i = foldr (\j -> Map.insert j j) mempty [1 .. i]--benchOrderedTraversal :: String -> Map.Map Integer Integer -> Criterion.Benchmark-benchOrderedTraversal dataLabel mapData =-    bgroup ("Ordered Traversals: " <> dataLabel)-        [ bench "traverseWithKey" $-            whnf (Map.traverseWithKey (\_ i -> pure @Maybe $ i ^ i)) mapData-        , bench "traverseWithKey_" $-            whnf (Map.traverseWithKey_ (\_ i -> pure @Maybe (i ^ i) *> pure ())) mapData-        ]--benchUnorderedTraversal :: String -> Map.Map Integer Integer -> Criterion.Benchmark-benchUnorderedTraversal dataLabel mapData =-    bgroup ("Unordered Traversals: " <> dataLabel)-        [ bench "unorderedTraverseWithKey_" $-            whnf (Map.unorderedTraverseWithKey_ (\_ i -> pure @Maybe (i ^ i) *> pure ())) mapData-        ]--main :: IO ()-main = do-    let !smallMap  = testData 10-        !mediumMap = testData 1000-        !largeMap  = testData 100000-    defaultMain-        [ benchOrderedTraversal   "small" smallMap-        , benchUnorderedTraversal "small" smallMap--        , benchOrderedTraversal   "medium" mediumMap-        , benchUnorderedTraversal "medium" mediumMap--        , benchOrderedTraversal   "large"  largeMap-        , benchUnorderedTraversal "large"  largeMap-        ]
benchmark/parser/Main.hs view
@@ -1,98 +1,91 @@-{-# LANGUAGE CPP               #-}+{-# LANGUAGE BangPatterns      #-} {-# LANGUAGE OverloadedStrings #-}  module Main where -import Control.Monad (forM)-import Criterion.Main (defaultMain, bgroup, bench, whnf, nfIO)-import Data.Map (Map, foldrWithKey, singleton, unions)-import Data.Monoid ((<>))--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 Criterion.Main as Criterion 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.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 "Prelude"+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 -> Criterion.Benchmark+benchParser :: PreludeFiles -> Benchmark benchParser =       bgroup "exprFromText"-    . foldrWithKey (\name expr -> (benchExprFromText name expr :)) []+    . Map.foldrWithKey (\name expr -> (benchExprFromText name expr :)) [] -benchExprFromText :: String -> T.Text -> Criterion.Benchmark-benchExprFromText name expr =+benchExprFromText :: String -> Text -> Benchmark+benchExprFromText name !expr =     bench name $ whnf (Dhall.exprFromText "(input)") expr -benchExprFromBytes-    :: String -> Data.ByteString.Lazy.ByteString -> Criterion.Benchmark-benchExprFromBytes name bytes = bench name (whnf f bytes)+benchExprFromBytes :: String -> Data.ByteString.Lazy.ByteString -> Benchmark+benchExprFromBytes name bs = bench name (nf f bs)   where-    f bytes = do-        term <- case Codec.Serialise.deserialiseOrFail bytes of-            Left  _    -> Nothing-            Right term -> return term-        case Dhall.Binary.decodeExpression term of-            Left  _          -> Nothing-            Right expression -> return expression+    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"     defaultMain-        [ bgroup "Issue #108"-            [ benchExprFromText  "Text"   issue108Text-            , benchExprFromBytes "Binary" issue108Bytes-            ]-        , 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,18 +1,3 @@-{--The `and` function returns `False` if there are any `False` elements in the-`List` and returns `True` otherwise--Examples:--```-./and [ True, False, True ] = False--./and ([] : List Bool) = True-```--}-let and-    : List Bool → Bool-    =   λ(xs : List Bool)-      → List/fold Bool xs Bool (λ(l : Bool) → λ(r : Bool) → l && r) True--in  and+  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,17 +1,3 @@-{--`build` is the inverse of `fold`--Examples:--```-./build (λ(bool : Type) → λ(true : bool) → λ(false : bool) → true) = True--./build (λ(bool : Type) → λ(true : bool) → λ(false : bool) → false) = False-```--}-let build-    : (∀(bool : Type) → ∀(true : bool) → ∀(false : bool) → bool) → Bool-    =   λ(f : ∀(bool : Type) → ∀(true : bool) → ∀(false : bool) → bool)-      → f Bool True False--in  build+  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,22 +1,3 @@-{--Returns `True` if there are an even number of `False` elements in the list and-returns `False` otherwise--Examples:--```-./even [ False, True, False ] = True--./even [ False, True ] = False--./even [ False ] = False--./even ([] : List Bool) = True-```--}-let even-    : List Bool → Bool-    =   λ(xs : List Bool)-      → List/fold Bool xs Bool (λ(x : Bool) → λ(y : Bool) → x == y) True--in  even+  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,20 +1,3 @@-{--`fold` is essentially the same as `if`/`then`/else` except as a function--Examples:--```-./fold True Natural 0 1 = 0--./fold False Natural 0 1 = 1-```--}-let fold-    : ∀(b : Bool) → ∀(bool : Type) → ∀(true : bool) → ∀(false : bool) → bool-    =   λ(b : Bool)-      → λ(bool : Type)-      → λ(true : bool)-      → λ(false : bool)-      → if b then true else false--in  fold+  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`--Examples:--```-./not True = False--./not False = True-```--}-let not : Bool → Bool = λ(b : Bool) → b == False 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,22 +1,3 @@-{--Returns `True` if there are an odd number of `True` elements in the list and-returns `False` otherwise--Examples:--```-./odd [ True, False, True ] = False--./odd [ True, False ] = True--./odd [ True ] = True--./odd ([] : List Bool) = False-```--}-let odd-    : List Bool → Bool-    =   λ(xs : List Bool)-      → List/fold Bool xs Bool (λ(x : Bool) → λ(y : Bool) → x != y) False--in  odd+  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,18 +1,3 @@-{--The `or` function returns `True` if there are any `True` elements in the `List`-and returns `False` otherwise--Examples:--```-./or [ True, False, True ] = True--./or ([] : List Bool) = False-```--}-let or-    : List Bool → Bool-    =   λ(xs : List Bool)-      → List/fold Bool xs Bool (λ(l : Bool) → λ(r : Bool) → l || r) False--in  or+  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)--Examples:--```-./show True  = "True"--./show False = "False"-```--}-let show : Bool → Text = λ(b : Bool) → if b then "True" else "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)--Examples:--```-./show -3.1 = "-3.1"--./show  0.4 =  "0.4"-```--}-let show : Double → Text = Double/show 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,21 +1,3 @@-{--Compose two functions into one.--Examples:--```-./compose Natural Natural Bool (λ(n : Natural) → n + n) ../Natural/even 3-= True-```--}-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)--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
@@ -0,0 +1,3 @@+  missing+    sha256:f78b96792b459cb664f41c6119bd8897dd04353a3343521d436cd82ad71cb4d4+? ./identity.dhall
+ dhall-lang/Prelude/Function/identity.dhall view
@@ -0,0 +1,10 @@+--| The identity function simply returns its input+let identity+    : ∀(a : Type) → ∀(x : a) → a+    = λ(a : Type) → λ(x : a) → x++let example0 = assert : identity Natural 1 ≡ 1++let example1 = assert : identity Bool ≡ (λ(x : Bool) → x)++in  identity
dhall-lang/Prelude/Function/package.dhall view
@@ -1,4 +1,13 @@ { compose =-      ./compose sha256:65ad8bbea530b3d8968785a7cf4a9a7976b67059aa15e3b61fcba600a40ae013-    ? ./compose+      missing+        sha256:65ad8bbea530b3d8968785a7cf4a9a7976b67059aa15e3b61fcba600a40ae013+    ? ./compose.dhall+, composeList =+      missing+        sha256:2c6931544d8b5a5b14514098c07bd1813f67b16834588d056df3c0bc2e489937+    ? ./composeList.dhall+, identity =+      missing+        sha256:f78b96792b459cb664f41c6119bd8897dd04353a3343521d436cd82ad71cb4d4+    ? ./identity.dhall }
+ dhall-lang/Prelude/Integer/abs view
@@ -0,0 +1,3 @@+  missing+    sha256:35212fcbe1e60cb95b033a4a9c6e45befca4a298aa9919915999d09e69ddced1+? ./abs.dhall
+ dhall-lang/Prelude/Integer/abs.dhall view
@@ -0,0 +1,15 @@+--| Returns the absolute value of an `Integer`, i.e. its non-negative value.+let abs+    : Integer → Natural+    = λ(n : Integer) →+        if    Natural/isZero (Integer/clamp n)+        then  Integer/clamp (Integer/negate n)+        else  Integer/clamp n++let example0 = assert : abs +7 ≡ 7++let example2 = assert : abs +0 ≡ 0++let example3 = assert : abs -3 ≡ 3++in  abs
+ dhall-lang/Prelude/Integer/add view
@@ -0,0 +1,3 @@+  missing+    sha256:7da1306a0bf87c5668beead2a1db1b18861e53d7ce1f38057b2964b649f59c3b+? ./add.dhall
+ dhall-lang/Prelude/Integer/add.dhall view
@@ -0,0 +1,25 @@+--| `add m n` computes `m + n`.+let Integer/subtract =+        missing+          sha256:a34d36272fa8ae4f1ec8b56222fe8dc8a2ec55ec6538b840de0cbe207b006fda+      ? ./subtract.dhall++let add+    : Integer → Integer → Integer+    = λ(m : Integer) → λ(n : Integer) → Integer/subtract (Integer/negate m) n++let example0 = assert : add +3 +5 ≡ +8++let example1 = assert : add -3 -5 ≡ -8++let example2 = assert : add -4 +4 ≡ +0++let example3 = assert : add -3 +5 ≡ +2++let example4 = assert : add +3 -5 ≡ -2++let example5 = assert : add +0 -3 ≡ -3++let example6 = assert : add +0 +3 ≡ +3++in  add
+ dhall-lang/Prelude/Integer/clamp view
@@ -0,0 +1,3 @@+  missing+    sha256:ea42096cf3e024fadfaf910e0b839005b0ea7514fff11e5a3950a77694d9c5d2+? ./clamp.dhall
+ dhall-lang/Prelude/Integer/clamp.dhall view
@@ -0,0 +1,14 @@+{-|+Convert an `Integer` to a `Natural` number, with negative numbers becoming zero.+-}+let clamp+    : Integer → Natural+    = Integer/clamp++let example0 = assert : clamp +7 ≡ 7++let example2 = assert : clamp +0 ≡ 0++let example3 = assert : clamp -3 ≡ 0++in  clamp
+ dhall-lang/Prelude/Integer/equal view
@@ -0,0 +1,3 @@+  missing+    sha256:2d99a205086aa77eea17ae1dab22c275f3eb007bccdc8d9895b93497ebfc39f8+? ./equal.dhall
+ dhall-lang/Prelude/Integer/equal.dhall view
@@ -0,0 +1,24 @@+--| `equal` checks if two Integers are equal.+let Natural/equal =+        missing+          sha256:7f108edfa35ddc7cebafb24dc073478e93a802e13b5bc3fd22f4768c9b066e60+      ? ../Natural/equal.dhall++let equal+    : Integer → Integer → Bool+    = λ(a : Integer) →+      λ(b : Integer) →+            Natural/equal (Integer/clamp a) (Integer/clamp b)+        &&  Natural/equal+              (Integer/clamp (Integer/negate a))+              (Integer/clamp (Integer/negate b))++let example0 = assert : equal +5 +5 ≡ True++let example1 = assert : equal +5 +6 ≡ False++let example2 = assert : equal +5 -5 ≡ False++let example3 = assert : equal -5 -5 ≡ True++in  equal
+ dhall-lang/Prelude/Integer/greaterThan view
@@ -0,0 +1,3 @@+  missing+    sha256:d23affd73029fc9aaf867c2c7b86510ca2802d3f0d1f3e1d1a93ffd87b7cb64b+? ./greaterThan.dhall
+ dhall-lang/Prelude/Integer/greaterThan.dhall view
@@ -0,0 +1,30 @@+--| `greaterThan` checks if one Integer is greater than another.+let Bool/not =+        missing+          sha256:723df402df24377d8a853afed08d9d69a0a6d86e2e5b2bac8960b0d4756c7dc4+      ? ../Bool/not.dhall++let lessThanEqual =+        missing+          sha256:e3cca9f3942f81fa78a2bea23c0c24519c67cfe438116c38e797e12dcd26f6bc+      ? ./lessThanEqual.dhall++let greaterThan+    : Integer → Integer → Bool+    = λ(x : Integer) → λ(y : Integer) → Bool/not (lessThanEqual x y)++let example0 = assert : greaterThan +5 +6 ≡ False++let example1 = assert : greaterThan +5 +5 ≡ False++let example2 = assert : greaterThan +5 +4 ≡ True++let example3 = assert : greaterThan -5 +8 ≡ False++let example4 = assert : greaterThan -5 -3 ≡ False++let example5 = assert : greaterThan -3 -5 ≡ True++let example6 = assert : greaterThan -3 -3 ≡ False++in  greaterThan
+ dhall-lang/Prelude/Integer/greaterThanEqual view
@@ -0,0 +1,3 @@+  missing+    sha256:a9fa2dc5cd6067a23b39d7fe8d14a63109583b320429fb0e446658a5aae0a958+? ./greaterThanEqual.dhall
+ dhall-lang/Prelude/Integer/greaterThanEqual.dhall view
@@ -0,0 +1,27 @@+{-|+`greaterThanEqual` checks if one Integer is greater than or equal to another.+-}+let lessThanEqual =+        missing+          sha256:e3cca9f3942f81fa78a2bea23c0c24519c67cfe438116c38e797e12dcd26f6bc+      ? ./lessThanEqual.dhall++let greaterThanEqual+    : Integer → Integer → Bool+    = λ(x : Integer) → λ(y : Integer) → lessThanEqual y x++let example0 = assert : greaterThanEqual +5 +6 ≡ False++let example1 = assert : greaterThanEqual +5 +5 ≡ True++let example2 = assert : greaterThanEqual +5 +4 ≡ True++let example3 = assert : greaterThanEqual -5 +8 ≡ False++let example4 = assert : greaterThanEqual -5 -3 ≡ False++let example5 = assert : greaterThanEqual -3 -5 ≡ True++let example6 = assert : greaterThanEqual -3 -3 ≡ True++in  greaterThanEqual
+ dhall-lang/Prelude/Integer/lessThan view
@@ -0,0 +1,3 @@+  missing+    sha256:eeaa0081d10c6c97464ef193c40f1aa5cbb12f0202972ab42f3d310c2fd6a3f0+? ./lessThan.dhall
+ dhall-lang/Prelude/Integer/lessThan.dhall view
@@ -0,0 +1,25 @@+--| `lessThan` checks if one Integer is less than another.+let greaterThan =+        missing+          sha256:d23affd73029fc9aaf867c2c7b86510ca2802d3f0d1f3e1d1a93ffd87b7cb64b+      ? ./greaterThan.dhall++let lessThan+    : Integer → Integer → Bool+    = λ(x : Integer) → λ(y : Integer) → greaterThan y x++let example0 = assert : lessThan +5 +6 ≡ True++let example1 = assert : lessThan +5 +5 ≡ False++let example2 = assert : lessThan +5 +4 ≡ False++let example3 = assert : lessThan -5 +8 ≡ True++let example4 = assert : lessThan -5 -3 ≡ True++let example5 = assert : lessThan -3 -5 ≡ False++let example6 = assert : lessThan -3 -3 ≡ False++in  lessThan
+ dhall-lang/Prelude/Integer/lessThanEqual view
@@ -0,0 +1,3 @@+  missing+    sha256:e3cca9f3942f81fa78a2bea23c0c24519c67cfe438116c38e797e12dcd26f6bc+? ./lessThanEqual.dhall
+ dhall-lang/Prelude/Integer/lessThanEqual.dhall view
@@ -0,0 +1,47 @@+--| `lessThanEqual` checks if one Integer is less than or equal to another.+let Natural/greaterThanEqual =+        missing+          sha256:30ebfab0febd7aa0ccccfdf3dc36ee6d50f0117f35dd4a9b034750b7e885a1a4+      ? ../Natural/greaterThanEqual.dhall++let Natural/lessThanEqual =+        missing+          sha256:1a5caa2b80a42b9f58fff58e47ac0d9a9946d0b2d36c54034b8ddfe3cb0f3c99+      ? ../Natural/lessThanEqual.dhall++let nonPositive =+        missing+          sha256:e00a852eed5b84ff60487097d8aadce53c9e5301f53ff4954044bd68949fac3b+      ? ./nonPositive.dhall++let nonNegative =+        missing+          sha256:b463373f070df6b1c8c7082051e0810fee38b360bab35256187c8c2b6af5c663+      ? ./nonNegative.dhall++let lessThanEqual+    : Integer → Integer → Bool+    = λ(x : Integer) →+      λ(y : Integer) →+        if    nonPositive x+        then      nonNegative y+              ||  Natural/greaterThanEqual+                    (Integer/clamp (Integer/negate x))+                    (Integer/clamp (Integer/negate y))+        else  Natural/lessThanEqual (Integer/clamp x) (Integer/clamp y)++let example0 = assert : lessThanEqual +5 +6 ≡ True++let example1 = assert : lessThanEqual +5 +5 ≡ True++let example2 = assert : lessThanEqual +5 +4 ≡ False++let example3 = assert : lessThanEqual -5 +8 ≡ True++let example4 = assert : lessThanEqual -5 -3 ≡ True++let example5 = assert : lessThanEqual -3 -5 ≡ False++let example6 = assert : lessThanEqual -3 -3 ≡ True++in  lessThanEqual
+ dhall-lang/Prelude/Integer/multiply view
@@ -0,0 +1,3 @@+  missing+    sha256:dcb1ed7c8475ece8d67db92cd249fc728541778ff82509e28c3760e341880e4d+? ./multiply.dhall
+ dhall-lang/Prelude/Integer/multiply.dhall view
@@ -0,0 +1,40 @@+--| `multiply m n` computes `m * n`.+let nonPositive =+        missing+          sha256:e00a852eed5b84ff60487097d8aadce53c9e5301f53ff4954044bd68949fac3b+      ? ./nonPositive.dhall++let multiplyNonNegative =+      λ(x : Integer) →+      λ(y : Integer) →+        Natural/toInteger (Integer/clamp x * Integer/clamp y)++let multiply+    : Integer → Integer → Integer+    = λ(m : Integer) →+      λ(n : Integer) →+        if    nonPositive m+        then  if    nonPositive n+              then  multiplyNonNegative (Integer/negate m) (Integer/negate n)+              else  Integer/negate (multiplyNonNegative (Integer/negate m) n)+        else  if nonPositive n+        then  Integer/negate (multiplyNonNegative m (Integer/negate n))+        else  multiplyNonNegative m n++let example0 = assert : multiply +3 +5 ≡ +15++let example1 = assert : multiply -3 +5 ≡ -15++let example2 = assert : multiply -3 -5 ≡ +15++let example3 = assert : multiply +0 +5 ≡ +0++let example4 = assert : multiply +5 +0 ≡ +0++let example5 = assert : multiply +0 +0 ≡ +0++let example6 = assert : multiply +1 +5 ≡ +5++let example7 = assert : multiply +3 -1 ≡ -3++in  multiply
+ dhall-lang/Prelude/Integer/negate view
@@ -0,0 +1,3 @@+  missing+    sha256:2373c992e1de93634bc6a8781eb073b2a92a70170133e49762a785f3a136df5d+? ./negate.dhall
+ dhall-lang/Prelude/Integer/negate.dhall view
@@ -0,0 +1,12 @@+--| Invert the sign of an `Integer`, with zero remaining unchanged.+let negate+    : Integer → Integer+    = Integer/negate++let example0 = assert : negate -3 ≡ +3++let example2 = assert : negate +7 ≡ -7++let example3 = assert : negate +0 ≡ +0++in  negate
+ dhall-lang/Prelude/Integer/negative view
@@ -0,0 +1,3 @@+  missing+    sha256:23e4b3c61eea9e878a7f83bf25fd0ea2c6a6d60174890d65be885828b690a570+? ./negative.dhall
+ dhall-lang/Prelude/Integer/negative.dhall view
@@ -0,0 +1,21 @@+{-|+Returns `True` for any `Integer` less than `+0`.++`negative` is more efficient than `./lessThan +0` or `./lessThanEqual -1`.+-}+let positive =+        missing+          sha256:7bdbf50fcdb83d01f74c7e2a92bf5c9104eff5d8c5b4587e9337f0caefcfdbe3+      ? ./positive.dhall++let negative+    : Integer → Bool+    = λ(n : Integer) → positive (Integer/negate n)++let example0 = assert : negative +1 ≡ False++let example1 = assert : negative +0 ≡ False++let example2 = assert : negative -1 ≡ True++in  negative
+ dhall-lang/Prelude/Integer/nonNegative view
@@ -0,0 +1,3 @@+  missing+    sha256:b463373f070df6b1c8c7082051e0810fee38b360bab35256187c8c2b6af5c663+? ./nonNegative.dhall
+ dhall-lang/Prelude/Integer/nonNegative.dhall view
@@ -0,0 +1,21 @@+{-|+Returns `True` for `+0` and any positive `Integer`.++`nonNegative` is more efficient than `./greaterThanEqual +0` or `./greaterThan -1`.+-}+let nonPositive =+        missing+          sha256:e00a852eed5b84ff60487097d8aadce53c9e5301f53ff4954044bd68949fac3b+      ? ./nonPositive.dhall++let nonNegative+    : Integer → Bool+    = λ(n : Integer) → nonPositive (Integer/negate n)++let example0 = assert : nonNegative +1 ≡ True++let example1 = assert : nonNegative +0 ≡ True++let example2 = assert : nonNegative -1 ≡ False++in  nonNegative
+ dhall-lang/Prelude/Integer/nonPositive view
@@ -0,0 +1,3 @@+  missing+    sha256:e00a852eed5b84ff60487097d8aadce53c9e5301f53ff4954044bd68949fac3b+? ./nonPositive.dhall
+ dhall-lang/Prelude/Integer/nonPositive.dhall view
@@ -0,0 +1,16 @@+{-|+Returns `True` for `+0` and any negative `Integer`.++`nonPositive` is more efficient than `./lessThanEqual +0` or `./lessThan +1`.+-}+let nonPositive+    : Integer → Bool+    = λ(n : Integer) → Natural/isZero (Integer/clamp n)++let example0 = assert : nonPositive +1 ≡ False++let example1 = assert : nonPositive +0 ≡ True++let example2 = assert : nonPositive -1 ≡ True++in  nonPositive
dhall-lang/Prelude/Integer/package.dhall view
@@ -1,7 +1,73 @@-{ show =-      ./show sha256:ecf8b0594cd5181bc45d3b7ea0d44d3ba9ad5dac6ec17bb8968beb65f4b1baa9-    ? ./show+{ abs =+      missing+        sha256:35212fcbe1e60cb95b033a4a9c6e45befca4a298aa9919915999d09e69ddced1+    ? ./abs.dhall+, add =+      missing+        sha256:7da1306a0bf87c5668beead2a1db1b18861e53d7ce1f38057b2964b649f59c3b+    ? ./add.dhall+, clamp =+      missing+        sha256:ea42096cf3e024fadfaf910e0b839005b0ea7514fff11e5a3950a77694d9c5d2+    ? ./clamp.dhall+, equal =+      missing+        sha256:2d99a205086aa77eea17ae1dab22c275f3eb007bccdc8d9895b93497ebfc39f8+    ? ./equal.dhall+, greaterThan =+      missing+        sha256:d23affd73029fc9aaf867c2c7b86510ca2802d3f0d1f3e1d1a93ffd87b7cb64b+    ? ./greaterThan.dhall+, greaterThanEqual =+      missing+        sha256:a9fa2dc5cd6067a23b39d7fe8d14a63109583b320429fb0e446658a5aae0a958+    ? ./greaterThanEqual.dhall+, lessThan =+      missing+        sha256:eeaa0081d10c6c97464ef193c40f1aa5cbb12f0202972ab42f3d310c2fd6a3f0+    ? ./lessThan.dhall+, lessThanEqual =+      missing+        sha256:e3cca9f3942f81fa78a2bea23c0c24519c67cfe438116c38e797e12dcd26f6bc+    ? ./lessThanEqual.dhall+, multiply =+      missing+        sha256:dcb1ed7c8475ece8d67db92cd249fc728541778ff82509e28c3760e341880e4d+    ? ./multiply.dhall+, negate =+      missing+        sha256:2373c992e1de93634bc6a8781eb073b2a92a70170133e49762a785f3a136df5d+    ? ./negate.dhall+, negative =+      missing+        sha256:23e4b3c61eea9e878a7f83bf25fd0ea2c6a6d60174890d65be885828b690a570+    ? ./negative.dhall+, nonNegative =+      missing+        sha256:b463373f070df6b1c8c7082051e0810fee38b360bab35256187c8c2b6af5c663+    ? ./nonNegative.dhall+, nonPositive =+      missing+        sha256:e00a852eed5b84ff60487097d8aadce53c9e5301f53ff4954044bd68949fac3b+    ? ./nonPositive.dhall+, positive =+      missing+        sha256:7bdbf50fcdb83d01f74c7e2a92bf5c9104eff5d8c5b4587e9337f0caefcfdbe3+    ? ./positive.dhall+, show =+      missing+        sha256:ecf8b0594cd5181bc45d3b7ea0d44d3ba9ad5dac6ec17bb8968beb65f4b1baa9+    ? ./show.dhall+, subtract =+      missing+        sha256:a34d36272fa8ae4f1ec8b56222fe8dc8a2ec55ec6538b840de0cbe207b006fda+    ? ./subtract.dhall , toDouble =-      ./toDouble sha256:77bc5d635dc4d952f37cc96f2a681d5ac503b4e8b21fc00055b1946adb5beda7-    ? ./toDouble+      missing+        sha256:77bc5d635dc4d952f37cc96f2a681d5ac503b4e8b21fc00055b1946adb5beda7+    ? ./toDouble.dhall+, toNatural =+      missing+        sha256:4d128730d74e7f832e53873cb5204aa91b79758be5ce4e1aa991fe1951304a0e+    ? ./toNatural.dhall }
+ dhall-lang/Prelude/Integer/positive view
@@ -0,0 +1,3 @@+  missing+    sha256:7bdbf50fcdb83d01f74c7e2a92bf5c9104eff5d8c5b4587e9337f0caefcfdbe3+? ./positive.dhall
+ dhall-lang/Prelude/Integer/positive.dhall view
@@ -0,0 +1,26 @@+{-|+Returns `True` for any `Integer` greater than `+0`.++`positive` is more efficient than `./greaterThan +0` or `./greaterThanEqual +1`.+-}+let not =+        missing+          sha256:723df402df24377d8a853afed08d9d69a0a6d86e2e5b2bac8960b0d4756c7dc4+      ? ../Bool/not.dhall++let nonPositive =+        missing+          sha256:e00a852eed5b84ff60487097d8aadce53c9e5301f53ff4954044bd68949fac3b+      ? ./nonPositive.dhall++let positive+    : Integer → Bool+    = λ(n : Integer) → not (nonPositive n)++let example0 = assert : positive +1 ≡ True++let example1 = assert : positive +0 ≡ False++let example2 = assert : positive -1 ≡ False++in  positive
dhall-lang/Prelude/Integer/show view
@@ -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)--Examples:--```-./show -3 = "-3"--./show +0 = "+0"-```--}-let show : Integer → Text = Integer/show 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
@@ -0,0 +1,3 @@+  missing+    sha256:a34d36272fa8ae4f1ec8b56222fe8dc8a2ec55ec6538b840de0cbe207b006fda+? ./subtract.dhall
+ dhall-lang/Prelude/Integer/subtract.dhall view
@@ -0,0 +1,54 @@+--| `subtract m n` computes `n - m`.+let nonPositive =+        missing+          sha256:e00a852eed5b84ff60487097d8aadce53c9e5301f53ff4954044bd68949fac3b+      ? ./nonPositive.dhall++let subtractNonNegative =+      λ(xi : Integer) →+      λ(yi : Integer) →+        let xn = Integer/clamp xi++        let yn = Integer/clamp yi++        let dn = Natural/subtract xn yn++        in  if    Natural/isZero dn+            then  Integer/negate (Natural/toInteger (Natural/subtract yn xn))+            else  Natural/toInteger dn++let subtract+    : Integer → Integer → Integer+    = λ(m : Integer) →+      λ(n : Integer) →+        if    nonPositive m+        then  if    nonPositive n+              then  subtractNonNegative (Integer/negate n) (Integer/negate m)+              else  Natural/toInteger+                      (Integer/clamp (Integer/negate m) + Integer/clamp n)+        else  if nonPositive n+        then  Integer/negate+                ( Natural/toInteger+                    (Integer/clamp m + Integer/clamp (Integer/negate n))+                )+        else  subtractNonNegative m n++let example0 = assert : subtract +3 +5 ≡ +2++let example1 = assert : subtract +4 +4 ≡ +0++let example2 = assert : subtract +5 +3 ≡ -2++let example3 = assert : subtract -3 -5 ≡ -2++let example4 = assert : subtract -4 -4 ≡ +0++let example5 = assert : subtract -5 -3 ≡ +2++let example6 = assert : subtract -3 +5 ≡ +8++let example7 = assert : subtract +3 -5 ≡ -8++let example8 = assert : subtract +0 -3 ≡ -3++in  subtract
dhall-lang/Prelude/Integer/toDouble view
@@ -1,12 +1,3 @@-{--Convert an `Integer` to the corresponding `Double`--Examples:--```-./toDouble -3 = -3.0--./toDouble +2 = 2.0-```--}-let toDouble : Integer → Double = Integer/toDouble 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
@@ -0,0 +1,3 @@+  missing+    sha256:4d128730d74e7f832e53873cb5204aa91b79758be5ce4e1aa991fe1951304a0e+? ./toNatural.dhall
+ dhall-lang/Prelude/Integer/toNatural.dhall view
@@ -0,0 +1,20 @@+{-|+Convert an `Integer` to an `Optional Natural`, with negative numbers becoming `None Natural`.+-}+let nonNegative =+        missing+          sha256:b463373f070df6b1c8c7082051e0810fee38b360bab35256187c8c2b6af5c663+      ? ./nonNegative.dhall++let toNatural+    : Integer → Optional Natural+    = λ(n : Integer) →+        if nonNegative n then Some (Integer/clamp n) else None Natural++let example0 = assert : toNatural +7 ≡ Some 7++let example2 = assert : toNatural +0 ≡ Some 0++let example3 = assert : toNatural -3 ≡ None Natural++in  toNatural
+ dhall-lang/Prelude/JSON/Format view
@@ -0,0 +1,3 @@+  missing+    sha256:d7936b510cfc091faa994652af0eb5feb889cd44bc989edbe4f1eb8c5623caac+? ./Format.dhall
+ dhall-lang/Prelude/JSON/Format.dhall view
@@ -0,0 +1,7 @@+{-|+An internal type used by `./renderAs` to select the output format.++You should not need to use this type directly, simply use `./render`+or `./renderYAML` as appropriate.+-}+< YAML | JSON >
dhall-lang/Prelude/JSON/Nesting view
@@ -1,31 +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,67 +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, 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
@@ -0,0 +1,3 @@+  missing+    sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759+? ./Type.dhall
+ dhall-lang/Prelude/JSON/Type.dhall view
@@ -0,0 +1,63 @@+{-|+Dhall encoding of an arbitrary JSON value++For example, the following JSON value:++```+[ { "foo": null, "bar": [ 1.0, true ] } ]+```++... corresponds to the following Dhall expression:++```+λ(JSON : Type) →+λ ( json+  : { array : List JSON → JSON+    , bool : Bool → JSON+    , null : JSON+    , double : Double → JSON+    , integer : Integer → JSON+    , object : List { mapKey : Text, mapValue : JSON } → JSON+    , string : Text → JSON+    }+  ) →+  json.object+    [ { mapKey = "foo", mapValue = json.null }+    , { mapKey = "bar"+      , mapValue = json.array [ json.double 1.0, json.bool True ]+      }+    ]+```++  You do not need to create these values directly, though.  You can use+  the utilities exported by `./package.dhall` to create values of this type,+  such as:++```+let JSON = ./package.dhall++in  JSON.object+      [ { mapKey = "foo", mapValue = JSON.null }+      , { mapKey = "bar"+        , mapValue = JSON.array [ JSON.double 1.0, JSON.bool True ]+        }+      ]+```++-}+let JSON/Type+    : Type+    = ∀(JSON : Type) →+      ∀ ( json+        : { array : List JSON → JSON+          , bool : Bool → JSON+          , double : Double → JSON+          , integer : Integer → JSON+          , null : JSON+          , object : List { mapKey : Text, mapValue : JSON } → JSON+          , string : Text → JSON+          }+        ) →+        JSON++in  JSON/Type
+ dhall-lang/Prelude/JSON/array view
@@ -0,0 +1,3 @@+  missing+    sha256:fb6346a9c63638fe3c59f8108e19eebdbddc51389ec5570bab4c25f890ccccc8+? ./array.dhall
+ dhall-lang/Prelude/JSON/array.dhall view
@@ -0,0 +1,41 @@+{-|+Create a JSON array from a `List` of JSON values++```+let JSON = ./package.dhall+in  JSON.render (JSON.array [ JSON.double 1.0, JSON.bool True ])+= "[ 1.0, true ]"++let JSON/Type = ./Type+let JSON = ./package.dhall+in  JSON.render (JSON.array ([] : List JSON/Type))+= "[ ]"+```+-}+let JSON =+        missing+          sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759+      ? ./Type.dhall++let List/map =+        missing+          sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+      ? ../List/map.dhall++let array+    : List JSON → JSON+    = λ(x : List JSON) →+      λ(JSON : Type) →+      λ ( json+        : { array : List JSON → JSON+          , bool : Bool → JSON+          , double : Double → JSON+          , integer : Integer → JSON+          , null : JSON+          , object : List { mapKey : Text, mapValue : JSON } → JSON+          , string : Text → JSON+          }+        ) →+        json.array (List/map JSON@1 JSON (λ(j : JSON@1) → j JSON json) x)++in  array
+ dhall-lang/Prelude/JSON/bool view
@@ -0,0 +1,3 @@+  missing+    sha256:e043d9ed01e5b45899059e128243f3dae7ce65f293f0015ce816fc36d30f7f39+? ./bool.dhall
+ dhall-lang/Prelude/JSON/bool.dhall view
@@ -0,0 +1,35 @@+{-|+Create a JSON bool from a Dhall `Bool`++```+let JSON = ./package.dhall+in  JSON.render (JSON.bool True)+= "true"++let JSON = ./package.dhall+in  JSON.render (JSON.bool False)+= "false"+```+-}+let JSON =+        missing+          sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759+      ? ./Type.dhall++let bool+    : Bool → JSON+    = λ(x : Bool) →+      λ(JSON : Type) →+      λ ( json+        : { array : List JSON → JSON+          , bool : Bool → JSON+          , double : Double → JSON+          , integer : Integer → JSON+          , null : JSON+          , object : List { mapKey : Text, mapValue : JSON } → JSON+          , string : Text → JSON+          }+        ) →+        json.bool x++in  bool
+ dhall-lang/Prelude/JSON/core.dhall view
@@ -0,0 +1,70 @@+{-|+A record of functions useful for constructing `JSON` values.++This is only a subset of what `package.dhall` exports. If you are not writing a+JSON prelude function, you should use the `package.dhall` file instead.++It is used internally by `render`, `renderYAML` and `omitNullFields` instead of+`package.dhall` to avoid import cycles.+-}+{ Type =+      missing+        sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759+    ? ./Type.dhall+, Tagged =+      missing+        sha256:21feca7d2b23f210d0696131d792e18a7d24fdcc85d41a49ba85b98670eba194+    ? ./Tagged.dhall+, Nesting =+      missing+        sha256:6284802edd41d5d725aa1ec7687e614e21ad1be7e14dd10996bfa9625105c335+    ? ./Nesting.dhall+, keyText =+      missing+        sha256:f7b6c802ca5764d03d5e9a6e48d9cb167c01392f775d9c2c87b83cdaa60ea0cc+    ? ./keyText.dhall+, keyValue =+      missing+        sha256:a0a97199d280c4cce72ffcbbf93b7ceda0a569cf4d173ac98e0aaaa78034b98c+    ? ./keyValue.dhall+, string =+      missing+        sha256:7ddb3a3b9f3ed09ed011d621a10ad9825185cd03503be98a81d42f6afb77940e+    ? ./string.dhall+, number =+      missing+        sha256:e70162c73c4978ad0d0d99505f61c7d990f3abadfcc08b34388b29c0934a7a32+    ? ./number.dhall+, double =+      missing+        sha256:e70162c73c4978ad0d0d99505f61c7d990f3abadfcc08b34388b29c0934a7a32+    ? ./double.dhall+, integer =+      missing+        sha256:c81a417397fc6f62155ec71fdd8d2047f981f0881295b307de3dd88747bf7e40+    ? ./integer.dhall+, natural =+      missing+        sha256:a839dc6789f19f820e9cbf70c60f41f3b057c59ece1d226d04db5aca447eb0e5+    ? ./natural.dhall+, object =+      missing+        sha256:869aede785c34798be9f9fd457ece73e7f683f352ae4555f791516a365faf4ac+    ? ./object.dhall+, array =+      missing+        sha256:fb6346a9c63638fe3c59f8108e19eebdbddc51389ec5570bab4c25f890ccccc8+    ? ./array.dhall+, bool =+      missing+        sha256:e043d9ed01e5b45899059e128243f3dae7ce65f293f0015ce816fc36d30f7f39+    ? ./bool.dhall+, null =+      missing+        sha256:1eeb9aee38eb8dde0e64efbaf60f24612c8194cc00b510bfb627c2ee2e1877b8+    ? ./null.dhall+, renderInteger =+      missing+        sha256:15b8d2ae46d5002832741927af787761df49798c911e2bf85db7a7b9cb5c078c+    ? ./renderInteger.dhall+}
+ dhall-lang/Prelude/JSON/double view
@@ -0,0 +1,3 @@+  missing+    sha256:e70162c73c4978ad0d0d99505f61c7d990f3abadfcc08b34388b29c0934a7a32+? ./double.dhall
+ dhall-lang/Prelude/JSON/double.dhall view
@@ -0,0 +1,35 @@+{-|+Create a JSON number from a Dhall `Double`++```+let JSON = ./package.dhall+in  JSON.render (JSON.double 42.0)+= "42.0"++let JSON = ./package.dhall+in  JSON.render (JSON.double -1.5e-10)+= "-1.5e-10"+```+-}+let JSON =+        missing+          sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759+      ? ./Type.dhall++let double+    : Double → JSON+    = λ(x : Double) →+      λ(JSON : Type) →+      λ ( json+        : { array : List JSON → JSON+          , bool : Bool → JSON+          , double : Double → JSON+          , integer : Integer → JSON+          , null : JSON+          , object : List { mapKey : Text, mapValue : JSON } → JSON+          , string : Text → JSON+          }+        ) →+        json.double x++in  double
+ dhall-lang/Prelude/JSON/integer view
@@ -0,0 +1,3 @@+  missing+    sha256:c81a417397fc6f62155ec71fdd8d2047f981f0881295b307de3dd88747bf7e40+? ./integer.dhall
+ dhall-lang/Prelude/JSON/integer.dhall view
@@ -0,0 +1,35 @@+{-|+Create a JSON number from a Dhall `Integer`++```+let JSON = ./package.dhall+in  JSON.render (JSON.integer -1)+= "-1"++let JSON = ./package.dhall+in  JSON.render (JSON.integer +2)+= "+2"+```+-}+let JSON =+        missing+          sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759+      ? ./Type.dhall++let integer+    : Integer → JSON+    = λ(x : Integer) →+      λ(JSON : Type) →+      λ ( json+        : { array : List JSON → JSON+          , bool : Bool → JSON+          , double : Double → JSON+          , integer : Integer → JSON+          , null : JSON+          , object : List { mapKey : Text, mapValue : JSON } → JSON+          , string : Text → JSON+          }+        ) →+        json.integer x++in  integer
dhall-lang/Prelude/JSON/keyText view
@@ -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.-Both key and value are fixed to Text.-Take a look at `Record/keyValue` for a polymorphic version.--Example:--```-./keyText "foo" "bar" = { mapKey = "foo", mapValue = "bar" }-```--}--let keyText =-      λ(key : Text) → λ(value : Text) → { mapKey = key, mapValue = value }--in  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,20 +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.--Examples:--```-./keyValue Natural "foo" 2 = { mapKey = "foo", mapValue = 2 }--./keyValue Text "bar" "baz" = { mapKey = "bar", mapValue = "baz" }-```--}--let keyValue =-        λ(v : Type)-      → λ(key : Text)-      → λ(value : v)-      → { mapKey = key, mapValue = value }--in  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
@@ -0,0 +1,3 @@+  missing+    sha256:a839dc6789f19f820e9cbf70c60f41f3b057c59ece1d226d04db5aca447eb0e5+? ./natural.dhall
+ dhall-lang/Prelude/JSON/natural.dhall view
@@ -0,0 +1,31 @@+{-|+Create a JSON number from a Dhall `Natural`++```+let JSON = ./package.dhall+in  JSON.render (JSON.natural 42)+= "42"+```+-}+let JSON =+        missing+          sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759+      ? ./Type.dhall++let natural+    : Natural → JSON+    = λ(x : Natural) →+      λ(JSON : Type) →+      λ ( json+        : { array : List JSON → JSON+          , bool : Bool → JSON+          , double : Double → JSON+          , integer : Integer → JSON+          , null : JSON+          , object : List { mapKey : Text, mapValue : JSON } → JSON+          , string : Text → JSON+          }+        ) →+        json.integer (Natural/toInteger x)++in  natural
+ dhall-lang/Prelude/JSON/null view
@@ -0,0 +1,3 @@+  missing+    sha256:1eeb9aee38eb8dde0e64efbaf60f24612c8194cc00b510bfb627c2ee2e1877b8+? ./null.dhall
+ dhall-lang/Prelude/JSON/null.dhall view
@@ -0,0 +1,30 @@+{-|+Create a JSON null++```+let JSON = ./package.dhall+in  JSON.render JSON.null+= "null"+```+-}+let JSON =+        missing+          sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759+      ? ./Type.dhall++let null+    : JSON+    = λ(JSON : Type) →+      λ ( json+        : { array : List JSON → JSON+          , bool : Bool → JSON+          , double : Double → JSON+          , integer : Integer → JSON+          , null : JSON+          , object : List { mapKey : Text, mapValue : JSON } → JSON+          , string : Text → JSON+          }+        ) →+        json.null++in  null
+ dhall-lang/Prelude/JSON/number view
@@ -0,0 +1,3 @@+  missing+    sha256:e70162c73c4978ad0d0d99505f61c7d990f3abadfcc08b34388b29c0934a7a32+? ./number.dhall
+ dhall-lang/Prelude/JSON/number.dhall view
@@ -0,0 +1,28 @@+{-|+Create a JSON number from a Dhall `Double`++```+let JSON = ./package.dhall+in  JSON.render (JSON.number 42.0)+= "42.0"++let JSON = ./package.dhall+in  JSON.render (JSON.number -1.5e-10)+= "-1.5e-10"+```+-}+let JSON =+        missing+          sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759+      ? ./Type.dhall++let double =+        missing+          sha256:e70162c73c4978ad0d0d99505f61c7d990f3abadfcc08b34388b29c0934a7a32+      ? ./double.dhall++let number+    : Double → JSON+    = double++in  number
+ dhall-lang/Prelude/JSON/object view
@@ -0,0 +1,3 @@+  missing+    sha256:869aede785c34798be9f9fd457ece73e7f683f352ae4555f791516a365faf4ac+? ./object.dhall
+ dhall-lang/Prelude/JSON/object.dhall view
@@ -0,0 +1,55 @@+{-|+Create a JSON object from a Dhall `Map`++```+let JSON = ./package.dhall+in  JSON.render+    ( JSON.object+      [ { mapKey = "foo", mapValue = JSON.double 1.0 }+      , { mapKey = "bar", mapValue = JSON.bool True  }+      ]+    )+= "{ \"foo\": 1.0, \"bar\": true }"++let JSON/Type = ./Type+let JSON = ./package.dhall+in  JSON.render+    (JSON.object ([] : List { mapKey : Text, mapValue : JSON/Type }))+= "{ }"+```+-}+let JSON =+        missing+          sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759+      ? ./Type.dhall++let List/map =+        missing+          sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+      ? ../List/map.dhall++let object+    : List { mapKey : Text, mapValue : JSON } → JSON+    = λ(x : List { mapKey : Text, mapValue : JSON }) →+      λ(JSON : Type) →+      λ ( json+        : { array : List JSON → JSON+          , bool : Bool → JSON+          , double : Double → JSON+          , integer : Integer → JSON+          , null : JSON+          , object : List { mapKey : Text, mapValue : JSON } → JSON+          , string : Text → JSON+          }+        ) →+        json.object+          ( List/map+              { mapKey : Text, mapValue : JSON@1 }+              { mapKey : Text, mapValue : JSON }+              ( λ(kv : { mapKey : Text, mapValue : JSON@1 }) →+                  { mapKey = kv.mapKey, mapValue = kv.mapValue JSON json }+              )+              x+          )++in  object
+ dhall-lang/Prelude/JSON/omitNullFields view
@@ -0,0 +1,3 @@+  missing+    sha256:e6850e70094540b75edeb46f4d6038324a62def8d63544a1e9541f79739db6f0+? ./omitNullFields.dhall
+ dhall-lang/Prelude/JSON/omitNullFields.dhall view
@@ -0,0 +1,145 @@+{-|+This utility omits all `null` record fields, which is often the idiomatic way+for a configuration to encode absent fields+-}+let JSON =+        missing+          sha256:5dc1135d5481cfd6fde625aaed9fcbdb7aa7c14f2e76726aa5fdef028a5c10f5+      ? ./core.dhall++let List/concatMap =+        missing+          sha256:3b2167061d11fda1e4f6de0522cbe83e0d5ac4ef5ddf6bb0b2064470c5d3fb64+      ? ../List/concatMap.dhall++let List/map =+        missing+          sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+      ? ../List/map.dhall++let omitNullFields+    : JSON.Type → JSON.Type+    = λ(old : JSON.Type) →+      λ(JSON : Type) →+      λ ( json+        : { array : List JSON → JSON+          , bool : Bool → JSON+          , double : Double → JSON+          , integer : Integer → JSON+          , null : JSON+          , object : List { mapKey : Text, mapValue : JSON } → JSON+          , string : Text → JSON+          }+        ) →+        let result =+              old+                { value : JSON, isNull : Bool }+                { string =+                    λ(x : Text) → { value = json.string x, isNull = False }+                , double =+                    λ(x : Double) → { value = json.double x, isNull = False }+                , integer =+                    λ(x : Integer) → { value = json.integer x, isNull = False }+                , object =+                    λ ( keyValues+                      : List+                          { mapKey : Text+                          , mapValue : { value : JSON, isNull : Bool }+                          }+                      ) →+                      let value =+                            json.object+                              ( List/concatMap+                                  { mapKey : Text+                                  , mapValue : { value : JSON, isNull : Bool }+                                  }+                                  { mapKey : Text, mapValue : JSON }+                                  ( λ ( keyValue+                                      : { mapKey : Text+                                        , mapValue :+                                            { value : JSON, isNull : Bool }+                                        }+                                      ) →+                                      if    keyValue.mapValue.isNull+                                      then  [] : List+                                                   { mapKey : Text+                                                   , mapValue : JSON+                                                   }+                                      else  [   keyValue.{ mapKey }+                                              ∧ { mapValue =+                                                    keyValue.mapValue.value+                                                }+                                            ]+                                  )+                                  keyValues+                              )++                      in  { value, isNull = False }+                , array =+                    λ(xs : List { value : JSON, isNull : Bool }) →+                      let value =+                            json.array+                              ( List/map+                                  { value : JSON, isNull : Bool }+                                  JSON+                                  ( λ(x : { value : JSON, isNull : Bool }) →+                                      x.value+                                  )+                                  xs+                              )++                      in  { value, isNull = False }+                , bool = λ(x : Bool) → { value = json.bool x, isNull = False }+                , null = { value = json.null, isNull = True }+                }++        in  result.value++let property =+      λ(a : Text) →+      λ(b : Double) →+      λ(c : Bool) →+          assert+        :   omitNullFields+              ( JSON.object+                  ( toMap+                      { string = JSON.string a+                      , double = JSON.double b+                      , bool = JSON.bool c+                      , null = JSON.null+                      }+                  )+              )+          ≡ JSON.object+              ( toMap+                  { string = JSON.string a+                  , double = JSON.double b+                  , bool = JSON.bool c+                  }+              )++let example =+        assert+      :   omitNullFields+            ( JSON.object+                ( toMap+                    { array =+                        JSON.array [ JSON.object (toMap { null = JSON.null }) ]+                    }+                )+            )+        ≡ JSON.object+            ( toMap+                { array =+                    JSON.array+                      [ JSON.object+                          ([] : List { mapKey : Text, mapValue : JSON.Type })+                      ]+                }+            )++let example =+        assert+      : omitNullFields (JSON.array [ JSON.null ]) ≡ JSON.array [ JSON.null ]++in  omitNullFields
dhall-lang/Prelude/JSON/package.dhall view
@@ -1,7 +1,29 @@-{ keyText =-      ./keyText sha256:f7b6c802ca5764d03d5e9a6e48d9cb167c01392f775d9c2c87b83cdaa60ea0cc-    ? ./keyText-, keyValue =-      ./keyValue sha256:a0a97199d280c4cce72ffcbbf93b7ceda0a569cf4d173ac98e0aaaa78034b98c-    ? ./keyValue-}+  { render =+        missing+          sha256:36befdd8bb5a1c2b372709da245a8d074533b86429e137b894c08ad16fa34836+      ? ./render.dhall+  , renderCompact =+        missing+          sha256:e6c8809fbe193fddd430f94350d69cefd45e7aaf8bd379e51b750fde75008562+      ? ./renderCompact.dhall+  , renderYAML =+        missing+          sha256:bc71449397bbf48103c3ebbdd570cd27313115e94b2b1b96761d257d5c02d478+      ? ./renderYAML.dhall+  , omitNullFields =+        missing+          sha256:e6850e70094540b75edeb46f4d6038324a62def8d63544a1e9541f79739db6f0+      ? ./omitNullFields.dhall+  , tagInline =+        missing+          sha256:49559ac11906ba6cc9eac25753e31e7addb13bc760df108024174c55523984c4+      ? ./tagInline.dhall+  , tagNested =+        missing+          sha256:93a7415853b7677c832246efadc8e880c1b641a23589286a836a384ca311d26f+      ? ./tagNested.dhall+  }+∧ (   missing+        sha256:5dc1135d5481cfd6fde625aaed9fcbdb7aa7c14f2e76726aa5fdef028a5c10f5+    ? ./core.dhall+  )
+ dhall-lang/Prelude/JSON/render view
@@ -0,0 +1,3 @@+  missing+    sha256:36befdd8bb5a1c2b372709da245a8d074533b86429e137b894c08ad16fa34836+? ./render.dhall
+ dhall-lang/Prelude/JSON/render.dhall view
@@ -0,0 +1,52 @@+{-|+Render a `JSON` value as `Text`++This is useful for debugging `JSON` values or for tests.  For anything+more sophisticated you should use `dhall-to-json` or `dhall-to-yaml`+-}+let JSON =+        missing+          sha256:5dc1135d5481cfd6fde625aaed9fcbdb7aa7c14f2e76726aa5fdef028a5c10f5+      ? ./core.dhall++let renderAs =+        missing+          sha256:c23be039c9601a33d6546fd99a8d72bee8dde5f46176d57cc96613b31a3bb471+      ? ./renderAs.dhall++let Format =+        missing+          sha256:d7936b510cfc091faa994652af0eb5feb889cd44bc989edbe4f1eb8c5623caac+      ? ./Format.dhall++let render+    : JSON.Type → Text+    = renderAs Format.JSON++let example0 =+      let data =+              assert+            :   render+                  ( JSON.array+                      [ JSON.bool True+                      , JSON.string "Hello"+                      , JSON.object+                          [ { mapKey = "foo", mapValue = JSON.null }+                          , { mapKey = "bar", mapValue = JSON.double 1.0 }+                          ]+                      ]+                  )+              ≡ ''+                [+                  true,+                  "Hello",+                  {+                    "foo": null,+                    "bar": 1.0+                  }+                ]+                ''++      in  True++in  render
+ dhall-lang/Prelude/JSON/renderAs view
@@ -0,0 +1,3 @@+  missing+    sha256:c23be039c9601a33d6546fd99a8d72bee8dde5f46176d57cc96613b31a3bb471+? ./renderAs.dhall
+ dhall-lang/Prelude/JSON/renderAs.dhall view
@@ -0,0 +1,458 @@+--| Render a `JSON` value as `Text` in either JSON or YAML format.+let JSON =+        missing+          sha256:5dc1135d5481cfd6fde625aaed9fcbdb7aa7c14f2e76726aa5fdef028a5c10f5+      ? ./core.dhall++let Function/identity =+        missing+          sha256:f78b96792b459cb664f41c6119bd8897dd04353a3343521d436cd82ad71cb4d4+      ? ../Function/identity.dhall++let Text/concatMap =+        missing+          sha256:7a0b0b99643de69d6f94ba49441cd0fa0507cbdfa8ace0295f16097af37e226f+      ? ../Text/concatMap.dhall++let List/map =+        missing+          sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+      ? ../List/map.dhall++let NonEmpty =+        missing+          sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+      ? ../NonEmpty/Type.dhall++let NonEmpty/toList =+        missing+          sha256:0977fe14b77232a4451dcf409c43df4589c4b3cdde7b613aab8df183be1b53f5+      ? ../NonEmpty/toList.dhall++let NonEmpty/concat =+        missing+          sha256:6d55181938c06c6b806877028f6a241912e9c0935d9a10dd958775bf21e0f64d+      ? ../NonEmpty/concat.dhall++let NonEmpty/map =+        missing+          sha256:93d53afe874bb2eed946c21ca5ada3c9716b7d00e6d8edfaba6484cd9c5a00bd+      ? ../NonEmpty/map.dhall++let NonEmpty/singleton =+        missing+          sha256:c9197aabe97695f7ca66f7419bf172d806b2c915594a8fc0d2ff6495db496ff2+      ? ../NonEmpty/singleton.dhall++let List/uncons+    : ∀(a : Type) → List a → Optional (NonEmpty a)+    = {- This version uses the `ls` argument only once to prevent cache blowups at the price+         of performing two passes over the list:+         A first one to reverse it, a second one with `List/fold` to determine+         the head element.+         See https://github.com/dhall-lang/dhall-lang/pull/1015#issuecomment-633381024+         for some context regarding the caching issue.+      -}+      λ(a : Type) →+      λ(ls : List a) →+        List/fold+          a+          (List/reverse a ls)+          (Optional (NonEmpty a))+          ( λ(x : a) →+            λ(acc : Optional (NonEmpty a)) →+              merge+                { None = Some (NonEmpty/singleton a x)+                , Some =+                    λ(ne : NonEmpty a) → Some (ne ⫽ { tail = ne.tail # [ x ] })+                }+                acc+          )+          (None (NonEmpty a))++let NonEmpty/mapHead+    : ∀(a : Type) → (a → a) → NonEmpty a → NonEmpty a+    = λ(a : Type) →+      λ(fn : a → a) →+      λ(ls : NonEmpty a) →+        ls ⫽ { head = fn ls.head }++let NonEmpty/mapTail+    : ∀(a : Type) → (a → a) → NonEmpty a → NonEmpty a+    = λ(a : Type) →+      λ(fn : a → a) →+      λ(ls : NonEmpty a) →+        ls ⫽ { tail = List/map a a fn ls.tail }++let NonEmpty/prepend+    : ∀(a : Type) → a → NonEmpty a → NonEmpty a+    = λ(a : Type) →+      λ(prefix : a) →+      λ(ls : NonEmpty a) →+        { head = prefix, tail = NonEmpty/toList a ls }++let NonYtpme+    : Type → Type+    = λ(a : Type) → { init : List a, last : a }++let List/unsnoc+    : ∀(a : Type) → List a → Optional (NonYtpme a)+    = λ(a : Type) →+      λ(ls : List a) →+        List/fold+          a+          ls+          (Optional (NonYtpme a))+          ( λ(x : a) →+            λ(acc : Optional (NonYtpme a)) →+              merge+                { None = Some { init = [] : List a, last = x }+                , Some =+                    λ(ny : NonYtpme a) → Some (ny ⫽ { init = [ x ] # ny.init })+                }+                acc+          )+          (None (NonYtpme a))++let NonEmpty/mapLast+    : ∀(a : Type) → (a → a) → NonEmpty a → NonEmpty a+    = λ(a : Type) →+      λ(fn : a → a) →+      λ(ls : NonEmpty a) →+        merge+          { Some = λ(x : NonYtpme a) → ls ⫽ { tail = x.init # [ fn x.last ] }+          , None = NonEmpty/singleton a (fn ls.head)+          }+          (List/unsnoc a ls.tail)++let NonEmpty/mapLeading+    : ∀(a : Type) → (a → a) → NonEmpty a → NonEmpty a+    = λ(a : Type) →+      λ(fn : a → a) →+      λ(ls : NonEmpty a) →+        merge+          { Some =+              λ(x : NonYtpme a) →+                { head = fn ls.head+                , tail = List/map a a fn x.init # [ x.last ]+                }+          , None = ls+          }+          (List/unsnoc a ls.tail)++let Lines+    : Type+    = NonEmpty Text++let Block+    : Type+    = < Simple : Text | Complex : Lines >++let Block/toLines+    : Block → Lines+    = λ(block : Block) →+        merge+          { Simple = NonEmpty/singleton Text+          , Complex = Function/identity Lines+          }+          block++let manyBlocks+    : ∀(a : Type) → Text → (NonEmpty a → Lines) → List a → Block+    = λ(a : Type) →+      λ(ifEmpty : Text) →+      λ(render : NonEmpty a → Lines) →+      λ(inputs : List a) →+        merge+          { Some = λ(inputs : NonEmpty a) → Block.Complex (render inputs)+          , None = Block.Simple ifEmpty+          }+          (List/uncons a inputs)++let blockToText+    : Block → Text+    = λ(block : Block) →+        Text/concatMap+          Text+          (λ(line : Text) → line ++ "\n")+          (NonEmpty/toList Text (Block/toLines block))++let addPrefix = λ(prefix : Text) → λ(line : Text) → prefix ++ line++let addIndent = addPrefix "  "++let indentTail = NonEmpty/mapTail Text addIndent++let Format =+        missing+          sha256:d7936b510cfc091faa994652af0eb5feb889cd44bc989edbe4f1eb8c5623caac+      ? ./Format.dhall++let ObjectField = { mapKey : Text, mapValue : Block }++let -- Essentially the same thing as `Text/show`, except that this does not+    -- escape `$`+    escape =+      List/fold+        (Text → Text)+        [ Text/replace "\"" "\\\""+        , Text/replace "\b" "\\b"+        , Text/replace "\f" "\\f"+        , Text/replace "\n" "\\n"+        , Text/replace "\r" "\\r"+        , Text/replace "\t" "\\t"+        , Text/replace "\\" "\\\\"+        ]+        Text+        (λ(replace : Text → Text) → λ(text : Text) → replace text)++let renderJSONStruct =+      λ(prefix : Text) →+      λ(suffix : Text) →+      λ(blocks : NonEmpty Lines) →+        let indent = List/map Text Text addIndent++        let appendComma+            : Lines → Lines+            = NonEmpty/mapLast Text (λ(line : Text) → line ++ ",")++        let blocks = NonEmpty/mapLeading Lines appendComma blocks++        let block = NonEmpty/concat Text blocks++        in  merge+              { None =+                  NonEmpty/singleton Text "${prefix} ${block.head} ${suffix}"+              , Some =+                  λ(ny : NonYtpme Text) →+                    { head = prefix+                    , tail =+                          indent ([ block.head ] # ny.init # [ ny.last ])+                        # [ suffix ]+                    }+              }+              (List/unsnoc Text block.tail)++let renderObject =+      λ(format : Format) →+      λ(fields : NonEmpty ObjectField) →+        let keystr = λ(field : ObjectField) → "\"${escape field.mapKey}\":"++        let prefixKeyOnFirst =+              λ(field : ObjectField) →+                NonEmpty/mapHead+                  Text+                  (addPrefix "${keystr field} ")+                  (Block/toLines field.mapValue)++        let prependKeyLine =+              λ(field : ObjectField) →+                NonEmpty/prepend+                  Text+                  (keystr field)+                  (Block/toLines field.mapValue)++        let renderYAMLField =+              λ(field : ObjectField) →+                merge+                  { Simple =+                      λ(line : Text) →+                        NonEmpty/singleton Text "${keystr field} ${line}"+                  , Complex = λ(_ : Lines) → indentTail (prependKeyLine field)+                  }+                  field.mapValue++        in  merge+              { JSON =+                  renderJSONStruct+                    "{"+                    "}"+                    (NonEmpty/map ObjectField Lines prefixKeyOnFirst fields)+              , YAML =+                  NonEmpty/concat+                    Text+                    (NonEmpty/map ObjectField Lines renderYAMLField fields)+              }+              format++let renderYAMLArrayField =+      λ(block : Block) →+        NonEmpty/mapHead+          Text+          (addPrefix "- ")+          (indentTail (Block/toLines block))++let renderArray =+      λ(format : Format) →+      λ(fields : NonEmpty Block) →+        merge+          { JSON =+              renderJSONStruct+                "["+                "]"+                (NonEmpty/map Block Lines Block/toLines fields)+          , YAML =+              NonEmpty/concat+                Text+                (NonEmpty/map Block Lines renderYAMLArrayField fields)+          }+          format++let renderAs+    : Format → JSON.Type → Text+    = λ(format : Format) →+      λ(json : JSON.Type) →+        blockToText+          ( json+              Block+              { string = λ(x : Text) → Block.Simple "\"${escape x}\""+              , double = λ(x : Double) → Block.Simple (Double/show x)+              , integer = λ(x : Integer) → Block.Simple (JSON.renderInteger x)+              , object = manyBlocks ObjectField "{}" (renderObject format)+              , array = manyBlocks Block "[]" (renderArray format)+              , bool =+                  λ(x : Bool) → Block.Simple (if x then "true" else "false")+              , null = Block.Simple "null"+              }+          )++let example0 =+      let data =+            JSON.array+              [ JSON.bool True+              , JSON.string "Hello"+              , JSON.object+                  [ { mapKey = "foo", mapValue = JSON.null }+                  , { mapKey = "bar", mapValue = JSON.double 1.0 }+                  ]+              ]++      let yaml =+              assert+            :   renderAs Format.YAML data+              ≡ ''+                - true+                - "Hello"+                - "foo": null+                  "bar": 1.0+                ''++      let json =+              assert+            :   renderAs Format.JSON data+              ≡ ''+                [+                  true,+                  "Hello",+                  {+                    "foo": null,+                    "bar": 1.0+                  }+                ]+                ''++      in  True++let example1 =+      let data =+            JSON.object+              [ { mapKey = "zero", mapValue = JSON.array ([] : List JSON.Type) }+              , { mapKey = "one", mapValue = JSON.array [ JSON.string "a" ] }+              , { mapKey = "two"+                , mapValue = JSON.array [ JSON.string "a", JSON.string "b" ]+                }+              ]++      let yaml =+              assert+            :   renderAs Format.YAML data+              ≡ ''+                "zero": []+                "one":+                  - "a"+                "two":+                  - "a"+                  - "b"+                ''++      let json =+              assert+            :   renderAs Format.JSON data+              ≡ ''+                {+                  "zero": [],+                  "one": [ "a" ],+                  "two": [+                    "a",+                    "b"+                  ]+                }+                ''++      in  True++let example2 =+      let data =+            JSON.object+              [ { mapKey = "zero"+                , mapValue =+                    JSON.object+                      (toMap {=} : List { mapKey : Text, mapValue : JSON.Type })+                }+              , { mapKey = "one"+                , mapValue = JSON.object (toMap { a = JSON.null })+                }+              , { mapKey = "two"+                , mapValue =+                    JSON.object (toMap { a = JSON.null, b = JSON.null })+                }+              ]++      let yaml =+              assert+            :   renderAs Format.YAML data+              ≡ ''+                "zero": {}+                "one":+                  "a": null+                "two":+                  "a": null+                  "b": null+                ''++      let json =+              assert+            :   renderAs Format.JSON data+              ≡ ''+                {+                  "zero": {},+                  "one": { "a": null },+                  "two": {+                    "a": null,+                    "b": null+                  }+                }+                ''++      in  True++let example3 =+      let specialCharacters =+            ''+            "\${"\b\f"}+            ${"\r"}	$''++      let data =+            JSON.object+              [ { mapKey = specialCharacters+                , mapValue = JSON.string specialCharacters+                }+              ]++      in    assert+          :   renderAs Format.JSON data+            ≡ ''+              { "\"\\\b\f\n\r\t$": "\"\\\b\f\n\r\t$" }+              ''++in  renderAs
+ dhall-lang/Prelude/JSON/renderCompact.dhall view
@@ -0,0 +1,61 @@+--| This renders JSON on a single line+let JSON =+        missing+          sha256:5dc1135d5481cfd6fde625aaed9fcbdb7aa7c14f2e76726aa5fdef028a5c10f5+      ? ./core.dhall++let Text/concatMapSep =+        missing+          sha256:c272aca80a607bc5963d1fcb38819e7e0d3e72ac4d02b1183b1afb6a91340840+      ? ../Text/concatMapSep++let renderInteger =+        missing+          sha256:15b8d2ae46d5002832741927af787761df49798c911e2bf85db7a7b9cb5c078c+      ? ./renderInteger.dhall++let renderCompact+    : JSON.Type → Text+    = λ(j : JSON.Type) →+        j+          Text+          { string = Text/show+          , double = Double/show+          , integer = renderInteger+          , object =+              λ(x : List { mapKey : Text, mapValue : Text }) →+                let body =+                      Text/concatMapSep+                        ","+                        { mapKey : Text, mapValue : Text }+                        ( λ(e : { mapKey : Text, mapValue : Text }) →+                            " ${Text/show e.mapKey}: ${e.mapValue}"+                        )+                        x++                in  "{${body} }"+          , array =+              λ(x : List Text) →+                let body = Text/concatMapSep "," Text (λ(y : Text) → " ${y}") x++                in  "[${body} ]"+          , bool = λ(x : Bool) → if x then "true" else "false"+          , null = "null"+          }++let example =+        assert+      :   renderCompact+            ( JSON.array+                [ JSON.bool True+                , JSON.string "Hello"+                , JSON.object+                    [ { mapKey = "foo", mapValue = JSON.null }+                    , { mapKey = "bar", mapValue = JSON.double 1.1 }+                    , { mapKey = "baz", mapValue = JSON.integer +2 }+                    ]+                ]+            )+        ≡ "[ true, \"Hello\", { \"foo\": null, \"bar\": 1.1, \"baz\": 2 } ]"++in  renderCompact
+ dhall-lang/Prelude/JSON/renderInteger.dhall view
@@ -0,0 +1,23 @@+{-|+Render an `Integer` value as a `JSON number`, according to the JSON standard, in+which a number may not start with a plus sign (`+`).+-}+let Integer/nonNegative =+        missing+          sha256:b463373f070df6b1c8c7082051e0810fee38b360bab35256187c8c2b6af5c663+      ? ../Integer/nonNegative.dhall++let renderInteger+    : Integer → Text+    = λ(integer : Integer) →+        if    Integer/nonNegative integer+        then  Natural/show (Integer/clamp integer)+        else  Integer/show integer++let positive = assert : renderInteger +1 ≡ "1"++let zero = assert : renderInteger +0 ≡ "0"++let negative = assert : renderInteger -1 ≡ "-1"++in  renderInteger
+ dhall-lang/Prelude/JSON/renderYAML view
@@ -0,0 +1,3 @@+  missing+    sha256:bc71449397bbf48103c3ebbdd570cd27313115e94b2b1b96761d257d5c02d478+? ./renderYAML.dhall
+ dhall-lang/Prelude/JSON/renderYAML.dhall view
@@ -0,0 +1,49 @@+{-|+Render a `JSON` value as `Text` in YAML format.++The generated YAML text will only contain escaped object keys and+string values and might therefore not be very human readable.++However, it is useful for debugging `JSON` values or for tests.+For anything more sophisticated you should use `dhall-to-json` or+`dhall-to-yaml`.+-}+let JSON =+        missing+          sha256:5dc1135d5481cfd6fde625aaed9fcbdb7aa7c14f2e76726aa5fdef028a5c10f5+      ? ./core.dhall++let renderAs =+        missing+          sha256:c23be039c9601a33d6546fd99a8d72bee8dde5f46176d57cc96613b31a3bb471+      ? ./renderAs.dhall++let Format =+        missing+          sha256:d7936b510cfc091faa994652af0eb5feb889cd44bc989edbe4f1eb8c5623caac+      ? ./Format.dhall++let renderYAML+    : JSON.Type → Text+    = renderAs Format.YAML++let example0 =+        assert+      :   renderYAML+            ( JSON.array+                [ JSON.bool True+                , JSON.string "Hello"+                , JSON.object+                    [ { mapKey = "foo", mapValue = JSON.null }+                    , { mapKey = "bar", mapValue = JSON.double 1.0 }+                    ]+                ]+            )+        ≡ ''+          - true+          - "Hello"+          - "foo": null+            "bar": 1.0+          ''++in  renderYAML
+ dhall-lang/Prelude/JSON/string view
@@ -0,0 +1,3 @@+  missing+    sha256:7ddb3a3b9f3ed09ed011d621a10ad9825185cd03503be98a81d42f6afb77940e+? ./string.dhall
+ dhall-lang/Prelude/JSON/string.dhall view
@@ -0,0 +1,35 @@+{-|+Create a JSON string from Dhall `Text`++```+let JSON = ./package.dhall+in  JSON.render (JSON.string "ABC $ \" 🙂")+= "\"ABC \\u0024 \\\" 🙂\""++let JSON = ./package.dhall+in  JSON.render (JSON.string "")+= "\"\""+```+-}+let JSON =+        missing+          sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759+      ? ./Type.dhall++let string+    : Text → JSON+    = λ(x : Text) →+      λ(JSON : Type) →+      λ ( json+        : { array : List JSON → JSON+          , bool : Bool → JSON+          , double : Double → JSON+          , integer : Integer → JSON+          , null : JSON+          , object : List { mapKey : Text, mapValue : JSON } → JSON+          , string : Text → JSON+          }+        ) →+        json.string x++in  string
+ dhall-lang/Prelude/JSON/tagInline view
@@ -0,0 +1,3 @@+  missing+    sha256:49559ac11906ba6cc9eac25753e31e7addb13bc760df108024174c55523984c4+? ./tagInline.dhall
+ dhall-lang/Prelude/JSON/tagInline.dhall view
@@ -0,0 +1,29 @@+--| Prepare a union value for JSON- or YAML-encoding with the inline layout+let Nesting =+        missing+          sha256:6284802edd41d5d725aa1ec7687e614e21ad1be7e14dd10996bfa9625105c335+      ? ./Nesting.dhall++let Tagged =+        missing+          sha256:21feca7d2b23f210d0696131d792e18a7d24fdcc85d41a49ba85b98670eba194+      ? ./Tagged.dhall++let tagInline+    : Text → ∀(a : Type) → a → Tagged a+    = λ(tagFieldName : Text) →+      λ(a : Type) →+      λ(contents : a) →+        { nesting = Nesting.Inline, field = tagFieldName, contents }++let example0 =+      let Example = < Left : { foo : Natural } | Right : { bar : Bool } >++      in    assert+          :   tagInline "name" Example (Example.Left { foo = 2 })+            ≡ { field = "name"+              , nesting = Nesting.Inline+              , contents = Example.Left { foo = 2 }+              }++in  tagInline
+ dhall-lang/Prelude/JSON/tagNested view
@@ -0,0 +1,3 @@+  missing+    sha256:93a7415853b7677c832246efadc8e880c1b641a23589286a836a384ca311d26f+? ./tagNested.dhall
+ dhall-lang/Prelude/JSON/tagNested.dhall view
@@ -0,0 +1,33 @@+--| Prepare a union value for JSON- or YAML-encoding with the nested layout+let Nesting =+        missing+          sha256:6284802edd41d5d725aa1ec7687e614e21ad1be7e14dd10996bfa9625105c335+      ? ./Nesting.dhall++let Tagged =+        missing+          sha256:21feca7d2b23f210d0696131d792e18a7d24fdcc85d41a49ba85b98670eba194+      ? ./Tagged.dhall++let tagNested+    : Text → Text → ∀(a : Type) → a → Tagged a+    = λ(contentsFieldName : Text) →+      λ(tagFieldName : Text) →+      λ(a : Type) →+      λ(contents : a) →+        { nesting = Nesting.Nested contentsFieldName+        , field = tagFieldName+        , contents+        }++let example0 =+      let Example = < Left : { foo : Natural } | Right : { bar : Bool } >++      in    assert+          :   tagNested "value" "name" Example (Example.Left { foo = 2 })+            ≡ { field = "name"+              , nesting = Nesting.Nested "value"+              , contents = Example.Left { foo = 2 }+              }++in  tagNested
dhall-lang/Prelude/List/all view
@@ -1,20 +1,3 @@-{--Returns `True` if the supplied function returns `True` for all elements in the-`List`--Examples:--```-./all Natural Natural/even [ 2, 3, 5 ] = False--./all Natural Natural/even ([] : List Natural) = True-```--}-let all-    : ∀(a : Type) → (a → Bool) → List a → Bool-    =   λ(a : Type)-      → λ(f : a → Bool)-      → λ(xs : List a)-      → List/fold a xs Bool (λ(x : a) → λ(r : Bool) → f x && r) True--in  all+  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,20 +1,3 @@-{--Returns `True` if the supplied function returns `True` for any element in the-`List`--Examples:--```-./any Natural Natural/even [ 2, 3, 5 ] = True--./any Natural Natural/even ([] : List Natural) = False-```--}-let any-    : ∀(a : Type) → (a → Bool) → List a → Bool-    =   λ(a : Type)-      → λ(f : a → Bool)-      → λ(xs : List a)-      → List/fold a xs Bool (λ(x : a) → λ(r : Bool) → f x || r) False--in  any+  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`--Examples:--```-./build-Text-(   λ(list : Type)-→   λ(cons : Text → list → list)-→   λ(nil : list)-→   cons "ABC" (cons "DEF" nil)-)-= [ "ABC", "DEF" ]--./build-Text-(   λ(list : Type)-→   λ(cons : Text → list → list)-→   λ(nil : list)-→   nil-)-= [] : List Text-```--}-let build-    :   ∀(a : Type)-      → (∀(list : Type) → ∀(cons : a → list → list) → ∀(nil : list) → list)-      → List a-    = List/build--in  build+  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,42 +1,3 @@-{--Concatenate a `List` of `List`s into a single `List`--Examples:--```-./concat Natural-[   [0, 1, 2]-,   [3, 4]-,   [5, 6, 7, 8]-]-= [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ]--./concat Natural-(   [   [] : List Natural-    ,   [] : List Natural-    ,   [] : List Natural-    ]-)-= [] : List Natural--./concat Natural ([] : List (List Natural)) = [] : List Natural-```--}-let concat-    : ∀(a : Type) → List (List a) → List a-    =   λ(a : Type)-      → λ(xss : List (List a))-      → List/build-        a-        (   λ(list : Type)-          → λ(cons : a → list → list)-          → λ(nil : list)-          → List/fold-            (List a)-            xss-            list-            (λ(xs : List a) → λ(ys : list) → List/fold a xs list cons ys)-            nil-        )--in  concat+  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,28 +1,3 @@-{--Transform a list by applying a function to each element and flattening the-results--Examples:--```-./concatMap Natural Natural (λ(n : Natural) → [n, n]) [2, 3, 5]-= [ 2, 2, 3, 3, 5, 5 ]--./concatMap Natural Natural (λ(n : Natural) → [n, n]) ([] : List Natural)-= [] : List Natural-```--}-let concatMap-    : ∀(a : Type) → ∀(b : Type) → (a → List b) → List a → List b-    =   λ(a : Type)-      → λ(b : Type)-      → λ(f : a → List b)-      → λ(xs : List a)-      → List/build-        b-        (   λ(list : Type)-          → λ(cons : b → list → list)-          → List/fold a xs list (λ(x : a) → List/fold b (f x) list cons)-        )--in  concatMap+  missing+    sha256:3b2167061d11fda1e4f6de0522cbe83e0d5ac4ef5ddf6bb0b2064470c5d3fb64+? ./concatMap.dhall
+ dhall-lang/Prelude/List/concatMap.dhall view
@@ -0,0 +1,32 @@+{-|+Transform a list by applying a function to each element and flattening the+results+-}+let concatMap+    : ∀(a : Type) → ∀(b : Type) → (a → List b) → List a → List b+    = λ(a : Type) →+      λ(b : Type) →+      λ(f : a → List b) →+      λ(xs : List a) →+        List/build+          b+          ( λ(list : Type) →+            λ(cons : b → list → list) →+              List/fold a xs list (λ(x : a) → List/fold b (f x) list cons)+          )++let example0 =+        assert+      :   concatMap Natural Natural (λ(n : Natural) → [ n, n ]) [ 2, 3, 5 ]+        ≡ [ 2, 2, 3, 3, 5, 5 ]++let example1 =+        assert+      :   concatMap+            Natural+            Natural+            (λ(n : Natural) → [ n, n ])+            ([] : List Natural)+        ≡ ([] : List Natural)++in  concatMap
+ dhall-lang/Prelude/List/default view
@@ -0,0 +1,3 @@+  missing+    sha256:fd77809e497227403f42848ffcda05a3efab442d961027c34f3e31d5d24e6379+? ./default.dhall
+ dhall-lang/Prelude/List/default.dhall view
@@ -0,0 +1,15 @@+{-|+Unpack an `Optional` containing a `List`, defaulting to an empty list when the+`Optional` is `None`+-}+let default+    : ∀(a : Type) → Optional (List a) → List a+    = λ(a : Type) →+      λ(o : Optional (List a)) →+        merge { Some = λ(l : List a) → l, None = [] : List a } o++let example0 = assert : default Bool (None (List Bool)) ≡ ([] : List Bool)++let example1 = assert : default Bool (Some [ True ]) ≡ [ True ]++in  default
+ dhall-lang/Prelude/List/drop view
@@ -0,0 +1,3 @@+  missing+    sha256:af983ba3ead494dd72beed05c0f3a17c36a4244adedf7ced502c6512196ed0cf+? ./drop.dhall
+ dhall-lang/Prelude/List/drop.dhall view
@@ -0,0 +1,28 @@+--| Remove first `n` elements of a list+let Natural/greaterThanEqual =+        missing+          sha256:30ebfab0febd7aa0ccccfdf3dc36ee6d50f0117f35dd4a9b034750b7e885a1a4+      ? ../Natural/greaterThanEqual.dhall++let drop+    : ∀(n : Natural) → ∀(a : Type) → List a → List a+    = λ(n : Natural) →+      λ(a : Type) →+      λ(xs : List a) →+        List/fold+          { index : Natural, value : a }+          (List/indexed a xs)+          (List a)+          ( λ(x : { index : Natural, value : a }) →+            λ(xs : List a) →+              if    Natural/greaterThanEqual x.index n+              then  [ x.value ] # xs+              else  xs+          )+          ([] : List a)++let example = assert : drop 2 Natural [ 2, 3, 5 ] ≡ [ 5 ]++let example = assert : drop 5 Natural [ 2, 3, 5 ] ≡ ([] : List Natural)++in  drop
+ dhall-lang/Prelude/List/empty view
@@ -0,0 +1,3 @@+  missing+    sha256:b2f561f35098c457353723c93a22bd5de28d26ecc5370814bef9dfda421e0147+? ./empty.dhall
+ dhall-lang/Prelude/List/empty.dhall view
@@ -0,0 +1,8 @@+--| An empty list of the given type+let empty+    : ∀(a : Type) → List a+    = λ(a : Type) → [] : List a++let example0 = assert : empty Bool ≡ ([] : List Bool)++in  empty
dhall-lang/Prelude/List/filter view
@@ -1,30 +1,3 @@-{--Only keep elements of the list where the supplied function returns `True`--Examples:--```-./filter Natural Natural/even [ 2, 3, 5 ]-= [ 2 ]--./filter Natural Natural/odd [ 2, 3, 5 ]-= [ 3, 5 ]-```--}-let filter-    : ∀(a : Type) → (a → Bool) → List a → List a-    =   λ(a : Type)-      → λ(f : a → Bool)-      → λ(xs : List a)-      → List/build-        a-        (   λ(list : Type)-          → λ(cons : a → list → list)-          → List/fold-            a-            xs-            list-            (λ(x : a) → λ(xs : list) → if f x then cons x xs else xs)-        )--in  filter+  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,46 +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--Examples:--```-    ./fold-    Natural-    [ 2, 3, 5 ]-    Natural-    (λ(x : Natural) → λ(y : Natural) → x + y)-    0-=   10--    λ(nil : Natural)-→   ./fold-    Natural-    [ 2, 3, 5 ]-    Natural-    (λ(x : Natural) → λ(y : Natural) → x + y)-    nil-=   λ(nil : Natural) → 2 + (3 + (5 + nil))--    λ(list : Type)-→   λ(cons : Natural → list → list)-→   λ(nil : list)-→   ./fold Natural [ 2, 3, 5 ] list cons nil-=   λ(list : Type)-→   λ(cons : Natural → list → list)-→   λ(nil : list)-→   cons 2 (cons 3 (cons 5 nil))-```--}-let fold-    :   ∀(a : Type)-      → List a-      → ∀(list : Type)-      → ∀(cons : a → list → list)-      → ∀(nil : list)-      → list-    = List/fold--in  fold+  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,38 +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--Examples:--```-./generate 5 Bool Natural/even = [ True, False, True, False, True ]--./generate 0 Bool Natural/even = [] : List Bool-```--}-let generate-    : Natural → ∀(a : Type) → (Natural → a) → List a-    =   λ(n : Natural)-      → λ(a : Type)-      → λ(f : Natural → a)-      → List/build-        a-        (   λ(list : Type)-          → λ(cons : a → list → list)-          → List/fold-            { index : Natural, value : {} }-            ( List/indexed-              {}-              ( List/build-                {}-                (   λ(list : Type)-                  → λ(cons : {} → list → list)-                  → Natural/fold n list (cons {=})-                )-              )-            )-            list-            (λ(x : { index : Natural, value : {} }) → cons (f x.index))-        )--in  generate+  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--Examples:--```-./head Natural [ 0, 1, 2 ] = Some 0--./head Natural ([] : List Natural) = None Natural-```--}-let head : ∀(a : Type) → List a → Optional a = List/head 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
@@ -0,0 +1,3 @@+  missing+    sha256:e657b55ecae4d899465c3032cb1a64c6aa6dc2aa3034204f3c15ce5c96c03e63+? ./index.dhall
+ dhall-lang/Prelude/List/index.dhall view
@@ -0,0 +1,18 @@+--| Retrieve an element from a `List` using its 0-based index+let drop =+        missing+          sha256:af983ba3ead494dd72beed05c0f3a17c36a4244adedf7ced502c6512196ed0cf+      ? ./drop.dhall++let index+    : Natural → ∀(a : Type) → List a → Optional a+    = λ(n : Natural) → λ(a : Type) → λ(xs : List a) → List/head a (drop n a xs)++let property =+      λ(n : Natural) → λ(a : Type) → assert : index n a ([] : List a) ≡ None a++let example0 = assert : index 1 Natural [ 2, 3, 5 ] ≡ Some 3++let example1 = assert : index 1 Natural ([] : List Natural) ≡ None Natural++in  index
dhall-lang/Prelude/List/indexed view
@@ -1,21 +1,3 @@-{--Tag each element of the list with its index--Examples:--```-./indexed Bool [ True, False, True ]-=   [   { index = 0, value = True  }-    ,   { index = 1, value = False }-    ,   { index = 2, value = True  }-    ] : List { index : Natural, value : Bool }--./indexed Bool ([] : List Bool)-= [] : List { index : Natural, value : Bool }-```--}-let indexed-    : ∀(a : Type) → List a → List { index : Natural, value : a }-    = List/indexed--in  indexed+  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,43 +1,3 @@-{--Generate a list of the specified length given a seed value and transition-function--Examples:--```-./iterate 10 Natural (λ(x : Natural) → x * 2) 1-= [ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512 ]--./iterate 0 Natural (λ(x : Natural) → x * 2) 1-= [] : List Natural-```--}-let iterate-    : Natural → ∀(a : Type) → (a → a) → a → List a-    =   λ(n : Natural)-      → λ(a : Type)-      → λ(f : a → a)-      → λ(x : a)-      → List/build-        a-        (   λ(list : Type)-          → λ(cons : a → list → list)-          → List/fold-            { index : Natural, value : {} }-            ( List/indexed-              {}-              ( List/build-                {}-                (   λ(list : Type)-                  → λ(cons : {} → list → list)-                  → Natural/fold n list (cons {=})-                )-              )-            )-            list-            (   λ(y : { index : Natural, value : {} })-              → cons (Natural/fold y.index a f x)-            )-        )--in  iterate+  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--Examples:--```-./last Natural [ 0, 1, 2 ] = Some 2--./last Natural ([] : List Natural) = None Natural-```--}-let last : ∀(a : Type) → List a → Optional a = List/last 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--Examples:--```-./length Natural [ 0, 1, 2 ] = 3--./length Natural ([] : List Natural) = 0-```--}-let length : ∀(a : Type) → List a → Natural = List/length 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,27 +1,3 @@-{--Transform a list by applying a function to each element--Examples:--```-./map Natural Bool Natural/even [ 2, 3, 5 ]-= [ True, False, False ]--./map Natural Bool Natural/even ([] : List Natural)-= [] : List Bool-```--}-let map-    : ∀(a : Type) → ∀(b : Type) → (a → b) → List a → List b-    =   λ(a : Type)-      → λ(b : Type)-      → λ(f : a → b)-      → λ(xs : List a)-      → List/build-        b-        (   λ(list : Type)-          → λ(cons : b → list → list)-          → List/fold a xs list (λ(x : a) → cons (f x))-        )--in  map+  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,16 +1,3 @@-{--Returns `True` if the `List` is empty and `False` otherwise--Examples:--```-./null Natural [ 0, 1, 2 ] = False--./null Natural ([] : List Natural) = True-```--}-let null-    : ∀(a : Type) → List a → Bool-    = λ(a : Type) → λ(xs : List a) → Natural/isZero (List/length a xs)--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,58 +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 =+      missing+        sha256:fd77809e497227403f42848ffcda05a3efab442d961027c34f3e31d5d24e6379+    ? ./default.dhall+, drop =+      missing+        sha256:af983ba3ead494dd72beed05c0f3a17c36a4244adedf7ced502c6512196ed0cf+    ? ./drop.dhall+, 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 =+      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 =+      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 =+      missing+        sha256:b3e08ee8c3a5bf3d8ccee6b2b2008fbb8e51e7373aef6f1af67ad10078c9fbfa+    ? ./take.dhall+, unpackOptionals =+      missing+        sha256:0cbaa920f429cf7fc3907f8a9143203fe948883913560e6e1043223e6b3d05e4+    ? ./unpackOptionals.dhall , unzip =-      ./unzip sha256:4d6003e9e683a289fe33f4c90f958eb1e08ea0bbb474210fcd90d1885c9660e9-    ? ./unzip+      missing+        sha256:4d6003e9e683a289fe33f4c90f958eb1e08ea0bbb474210fcd90d1885c9660e9+    ? ./unzip.dhall+, zip =+      missing+        sha256:85ed955eabf3998767f4ad2a28e57d40cd4c68a95519d79e9b622f1d26d979da+    ? ./zip.dhall }
+ dhall-lang/Prelude/List/partition view
@@ -0,0 +1,3 @@+  missing+    sha256:38147ac6d750a6492736dd90cc967bf09aa405c499de943c64fab7b86ae02f03+? ./partition.dhall
+ dhall-lang/Prelude/List/partition.dhall view
@@ -0,0 +1,31 @@+{-|+`partition` divides a `List` of elements into those that satisfy a predicate+and those that do not+-}+let Partition+    : Type → Type+    = λ(a : Type) → { true : List a, false : List a }++let partition+    : ∀(a : Type) → (a → Bool) → List a → Partition a+    = λ(a : Type) →+      λ(f : a → Bool) →+      λ(xs : List a) →+        List/fold+          a+          xs+          (Partition a)+          ( λ(x : a) →+            λ(p : Partition a) →+              if    f x+              then  { true = [ x ] # p.true, false = p.false }+              else  { true = p.true, false = [ x ] # p.false }+          )+          { true = [] : List a, false = [] : List a }++let example0 =+        assert+      :   partition Natural Natural/even [ 0, 1, 2, 3 ]+        ≡ { true = [ 0, 2 ], false = [ 1, 3 ] }++in  partition
dhall-lang/Prelude/List/replicate view
@@ -1,24 +1,3 @@-{--Build a list by copying the given element the specified number of times--Examples:--```-./replicate 9 Natural 1 = [ 1, 1, 1, 1, 1, 1, 1, 1, 1 ]--./replicate 0 Natural 1 = [] : List Natural-```--}-let replicate-    : Natural → ∀(a : Type) → a → List a-    =   λ(n : Natural)-      → λ(a : Type)-      → λ(x : a)-      → List/build-        a-        (   λ(list : Type)-          → λ(cons : a → list → list)-          → Natural/fold n list (cons x)-        )--in  replicate+  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,12 +1,3 @@-{--Reverse a list--Examples:--```-./reverse Natural [ 0, 1, 2 ] = [ 2, 1, 0 ] : List Natural--./reverse Natural ([] : List Natural) = [] : List Natural-```--}-let reverse : ∀(a : Type) → List a → List a = List/reverse 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,86 +1,3 @@-{--Combine a `List` of `List`s, offsetting the `index` of each element by the-number of elements in preceding lists--Examples:--```-./shifted-Bool-[   [   { index = 0, value = True  }-    ,   { index = 1, value = True  }-    ,   { index = 2, value = True  }-    ]-,   [   { index = 0, value = False }-    ,   { index = 1, value = False }-    ]-,   [   { index = 0, value = True  }-    ,   { index = 1, value = True  }-    ,   { index = 2, value = True  }-    ,   { index = 3, value = True  }-    ]-]-=   [   { index = 0, value = True  }-    ,   { index = 1, value = True  }-    ,   { index = 2, value = True  }-    ,   { index = 3, value = False }-    ,   { index = 4, value = False }-    ,   { index = 5, value = True  }-    ,   { index = 6, value = True  }-    ,   { index = 7, value = True  }-    ,   { index = 8, value = True  }-    ]--./shifted Bool ([] : List (List { index : Natural, value : Bool }))-= [] : List { index : Natural, value : Bool }-```--}-let shifted-    :   ∀(a : Type)-      → List (List { index : Natural, value : a })-      → List { index : Natural, value : a }-    =   λ(a : Type)-      → λ(kvss : List (List { index : Natural, value : a }))-      → List/build-        { index : Natural, value : a }-        (   λ(list : Type)-          → λ(cons : { index : Natural, value : a } → list → list)-          → λ(nil : list)-          → let result =-                  List/fold-                  (List { index : Natural, value : a })-                  kvss-                  { count : Natural, diff : Natural → list }-                  (   λ(kvs : List { index : Natural, value : a })-                    → λ(y : { count : Natural, diff : Natural → list })-                    → let length =-                            List/length { index : Natural, value : a } kvs-                      -                      in  { count =-                              y.count + length-                          , diff =-                                λ(n : Natural)-                              → List/fold-                                { index : Natural, value : a }-                                kvs-                                list-                                (   λ(kvOld : { index : Natural, value : a })-                                  → λ(z : list)-                                  → let kvNew =-                                          { index =-                                              kvOld.index + n-                                          , value =-                                              kvOld.value-                                          }-                                    -                                    in  cons kvNew z-                                )-                                (y.diff (n + length))-                          }-                  )-                  { count = 0, diff = λ(_ : Natural) → nil }-            -            in  result.diff 0-        )--in  shifted+  missing+    sha256:54fb22c7e952ebce1cfc0fcdd33ce4cfa817bff9d6564af268dea6685f8b5dfe+? ./shifted.dhall
+ dhall-lang/Prelude/List/shifted.dhall view
@@ -0,0 +1,83 @@+{-|+Combine a `List` of `List`s, offsetting the `index` of each element by the+number of elements in preceding lists+-}+let shifted+    : ∀(a : Type) →+      List (List { index : Natural, value : a }) →+        List { index : Natural, value : a }+    = λ(a : Type) →+      λ(kvss : List (List { index : Natural, value : a })) →+        List/build+          { index : Natural, value : a }+          ( λ(list : Type) →+            λ(cons : { index : Natural, value : a } → list → list) →+            λ(nil : list) →+              let result =+                    List/fold+                      (List { index : Natural, value : a })+                      kvss+                      { count : Natural, diff : Natural → list }+                      ( λ(kvs : List { index : Natural, value : a }) →+                        λ(y : { count : Natural, diff : Natural → list }) →+                          let length =+                                List/length { index : Natural, value : a } kvs++                          in  { count = y.count + length+                              , diff =+                                  λ(n : Natural) →+                                    List/fold+                                      { index : Natural, value : a }+                                      kvs+                                      list+                                      ( λ ( kvOld+                                          : { index : Natural, value : a }+                                          ) →+                                        λ(z : list) →+                                          let kvNew =+                                                { index = kvOld.index + n+                                                , value = kvOld.value+                                                }++                                          in  cons kvNew z+                                      )+                                      (y.diff (n + length))+                              }+                      )+                      { count = 0, diff = λ(_ : Natural) → nil }++              in  result.diff 0+          )++let example0 =+        assert+      :   shifted+            Bool+            [ [ { index = 0, value = True }+              , { index = 1, value = True }+              , { index = 2, value = True }+              ]+            , [ { index = 0, value = False }, { index = 1, value = False } ]+            , [ { index = 0, value = True }+              , { index = 1, value = True }+              , { index = 2, value = True }+              , { index = 3, value = True }+              ]+            ]+        ≡ [ { index = 0, value = True }+          , { index = 1, value = True }+          , { index = 2, value = True }+          , { index = 3, value = False }+          , { index = 4, value = False }+          , { index = 5, value = True }+          , { index = 6, value = True }+          , { index = 7, value = True }+          , { index = 8, value = True }+          ]++let example1 =+        assert+      :   shifted Bool ([] : List (List { index : Natural, value : Bool }))+        ≡ ([] : List { index : Natural, value : Bool })++in  shifted
+ dhall-lang/Prelude/List/take view
@@ -0,0 +1,3 @@+  missing+    sha256:b3e08ee8c3a5bf3d8ccee6b2b2008fbb8e51e7373aef6f1af67ad10078c9fbfa+? ./take.dhall
+ dhall-lang/Prelude/List/take.dhall view
@@ -0,0 +1,26 @@+--| Truncate a list to the first `n` elements+let Natural/lessThan =+        missing+          sha256:3381b66749290769badf8855d8a3f4af62e8de52d1364d838a9d1e20c94fa70c+      ? ../Natural/lessThan.dhall++let take+    : ∀(n : Natural) → ∀(a : Type) → List a → List a+    = λ(n : Natural) →+      λ(a : Type) →+      λ(xs : List a) →+        List/fold+          { index : Natural, value : a }+          (List/indexed a xs)+          (List a)+          ( λ(x : { index : Natural, value : a }) →+            λ(xs : List a) →+              if Natural/lessThan x.index n then [ x.value ] # xs else xs+          )+          ([] : List a)++let example = assert : take 2 Natural [ 2, 3, 5 ] ≡ [ 2, 3 ]++let example = assert : take 5 Natural [ 2, 3, 5 ] ≡ [ 2, 3, 5 ]++in  take
+ dhall-lang/Prelude/List/unpackOptionals view
@@ -0,0 +1,3 @@+  missing+    sha256:0cbaa920f429cf7fc3907f8a9143203fe948883913560e6e1043223e6b3d05e4+? ./unpackOptionals.dhall
+ dhall-lang/Prelude/List/unpackOptionals.dhall view
@@ -0,0 +1,31 @@+--| Unpack Optionals in a List, omitting None items.+let List/filterMap =+        missing+          sha256:94b7ed4204d1c79aaf55527ef51024e7085b8dd2896952cffbd12d8f95e16f46+      ? ./filterMap.dhall++let unpackOptionals+    : ∀(a : Type) → ∀(l : List (Optional a)) → List a+    = λ(a : Type) → List/filterMap (Optional a) a (λ(x : Optional a) → x)++let property1 =+      λ(a : Type) → λ(x : a) → assert : unpackOptionals a [ Some x ] ≡ [ x ]++let property2 =+      λ(a : Type) → assert : unpackOptionals a [ None a ] ≡ ([] : List a)++let example0 =+        assert+      : unpackOptionals Natural [ Some 1, None Natural, Some 3 ] ≡ [ 1, 3 ]++let example1 =+        assert+      :   unpackOptionals Natural ([] : List (Optional Natural))+        ≡ ([] : List Natural)++let example2 =+        assert+      :   unpackOptionals Natural [ None Natural, None Natural ]+        ≡ ([] : List Natural)++in  unpackOptionals
dhall-lang/Prelude/List/unzip view
@@ -1,55 +1,3 @@-{--Unzip a `List` into two separate `List`s--Examples:--```-./unzip-Text-Bool-(   [   { _1 = "ABC", _2 = True  }-    ,   { _1 = "DEF", _2 = False }-    ,   { _1 = "GHI", _2 = True  }-    ]-)-=   { _1 = [ "ABC", "DEF", "GHI" ]-    , _2 = [ True, False, True ]-    }--./unzip Text Bool ([] : List { _1 : Text, _2 : Bool })-= { _1 = [] : List Text, _2 = [] : List Bool }-```--}-let unzip-    :   ∀(a : Type)-      → ∀(b : Type)-      → List { _1 : a, _2 : b }-      → { _1 : List a, _2 : List b }-    =   λ(a : Type)-      → λ(b : Type)-      → λ(xs : List { _1 : a, _2 : b })-      → { _1 =-            List/build-            a-            (   λ(list : Type)-              → λ(cons : a → list → list)-              → List/fold-                { _1 : a, _2 : b }-                xs-                list-                (λ(x : { _1 : a, _2 : b }) → cons x._1)-            )-        , _2 =-            List/build-            b-            (   λ(list : Type)-              → λ(cons : b → list → list)-              → List/fold-                { _1 : a, _2 : b }-                xs-                list-                (λ(x : { _1 : a, _2 : b }) → cons x._2)-            )-        }--in  unzip+  missing+    sha256:4d6003e9e683a289fe33f4c90f958eb1e08ea0bbb474210fcd90d1885c9660e9+? ./unzip.dhall
+ dhall-lang/Prelude/List/unzip.dhall view
@@ -0,0 +1,50 @@+--| Unzip a `List` into two separate `List`s+let unzip+    : ∀(a : Type) →+      ∀(b : Type) →+      List { _1 : a, _2 : b } →+        { _1 : List a, _2 : List b }+    = λ(a : Type) →+      λ(b : Type) →+      λ(xs : List { _1 : a, _2 : b }) →+        { _1 =+            List/build+              a+              ( λ(list : Type) →+                λ(cons : a → list → list) →+                  List/fold+                    { _1 : a, _2 : b }+                    xs+                    list+                    (λ(x : { _1 : a, _2 : b }) → cons x._1)+              )+        , _2 =+            List/build+              b+              ( λ(list : Type) →+                λ(cons : b → list → list) →+                  List/fold+                    { _1 : a, _2 : b }+                    xs+                    list+                    (λ(x : { _1 : a, _2 : b }) → cons x._2)+              )+        }++let example0 =+        assert+      :   unzip+            Text+            Bool+            [ { _1 = "ABC", _2 = True }+            , { _1 = "DEF", _2 = False }+            , { _1 = "GHI", _2 = True }+            ]+        ≡ { _1 = [ "ABC", "DEF", "GHI" ], _2 = [ True, False, True ] }++let example1 =+        assert+      :   unzip Text Bool ([] : List { _1 : Text, _2 : Bool })+        ≡ { _1 = [] : List Text, _2 = [] : List Bool }++in  unzip
+ dhall-lang/Prelude/List/zip view
@@ -0,0 +1,3 @@+  missing+    sha256:85ed955eabf3998767f4ad2a28e57d40cd4c68a95519d79e9b622f1d26d979da+? ./zip.dhall
+ dhall-lang/Prelude/List/zip.dhall view
@@ -0,0 +1,58 @@+{-|+Zip two `List` into a single `List`++The resulting `List` will have the length of the shortest of its arguments.+-}+let List/index =+        missing+          sha256:e657b55ecae4d899465c3032cb1a64c6aa6dc2aa3034204f3c15ce5c96c03e63+      ? ./index.dhall++let zip+    : ∀(a : Type) → List a → ∀(b : Type) → List b → List { _1 : a, _2 : b }+    = λ(a : Type) →+      λ(xs : List a) →+      λ(b : Type) →+      λ(ys : List b) →+        let ixs = List/indexed a xs++        in  List/build+              { _1 : a, _2 : b }+              ( λ(list : Type) →+                λ(cons : { _1 : a, _2 : b } → list → list) →+                λ(nil : list) →+                  List/fold+                    { index : Natural, value : a }+                    ixs+                    list+                    ( λ(ix : { index : Natural, value : a }) →+                      λ(rest : list) →+                        merge+                          { None = rest+                          , Some =+                              λ(y : b) → cons { _1 = ix.value, _2 = y } rest+                          }+                          (List/index ix.index b ys)+                    )+                    nil+              )++let example0 =+        assert+      :   zip Text [ "ABC", "DEF", "GHI" ] Natural [ 1, 2, 3 ]+        ≡ [ { _1 = "ABC", _2 = 1 }+          , { _1 = "DEF", _2 = 2 }+          , { _1 = "GHI", _2 = 3 }+          ]++let example1 =+        assert+      :   zip Text [ "ABC" ] Bool ([] : List Bool)+        ≡ ([] : List { _1 : Text, _2 : Bool })++let example2 =+        assert+      :   zip Text [ "ABC", "DEF", "GHI" ] Natural [ 1 ]+        ≡ [ { _1 = "ABC", _2 = 1 } ]++in  zip
+ dhall-lang/Prelude/Location/Type view
@@ -0,0 +1,3 @@+  missing+    sha256:613ebb491aeef4ff06368058b4f0e6e3bb8a58d8c145131fc0b947aac045a529+? ./Type.dhall
+ dhall-lang/Prelude/Location/Type.dhall view
@@ -0,0 +1,15 @@+--| This is the union type returned when you import something `as Location`+let Location+    : Type+    = < Environment : Text | Local : Text | Missing | Remote : Text >++let example0 =+        assert+      :   missing as Location+        ≡ < Environment : Text+          | Local : Text+          | Missing+          | Remote : Text+          >.Missing++in  Location
+ dhall-lang/Prelude/Location/package.dhall view
@@ -0,0 +1,5 @@+{ Type =+      missing+        sha256:613ebb491aeef4ff06368058b4f0e6e3bb8a58d8c145131fc0b947aac045a529+    ? ./Type.dhall+}
+ dhall-lang/Prelude/Map/Entry view
@@ -0,0 +1,3 @@+  missing+    sha256:f334283bdd9cd88e6ea510ca914bc221fc2dab5fb424d24514b2e0df600d5346+? ./Entry.dhall
+ dhall-lang/Prelude/Map/Entry.dhall view
@@ -0,0 +1,6 @@+--| The type of each key-value pair in a `Map`+let Entry+    : Type → Type → Type+    = λ(k : Type) → λ(v : Type) → { mapKey : k, mapValue : v }++in  Entry
+ dhall-lang/Prelude/Map/Type view
@@ -0,0 +1,3 @@+  missing+    sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed+? ./Type.dhall
+ dhall-lang/Prelude/Map/Type.dhall view
@@ -0,0 +1,25 @@+{-|+This is the canonical way to encode a dynamic list of key-value pairs.++Tools (such as `dhall-to-json`/`dhall-to-yaml` will recognize values of this+type and convert them to maps/dictionaries/hashes in the target language++For example, `dhall-to-json` converts a Dhall value like this:++```+[ { mapKey = "foo", mapValue = 1 }+, { mapKey = "bar", mapValue = 2 }+] : ./Map Text Natural+```++... to a JSON value like this:++```+{ "foo": 1, "bar", 2 }+```+-}+let Map+    : Type → Type → Type+    = λ(k : Type) → λ(v : Type) → List { mapKey : k, mapValue : v }++in  Map
+ dhall-lang/Prelude/Map/empty view
@@ -0,0 +1,3 @@+  missing+    sha256:4c612558b8bbe8f955550ed3fb295d57b1b864c85cd52615b52d0ee0e9682e52+? ./empty.dhall
+ dhall-lang/Prelude/Map/empty.dhall view
@@ -0,0 +1,14 @@+--| An empty `Map` of the given key and value types+let Map =+        missing+          sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed+      ? ./Type.dhall++let empty+    : ∀(k : Type) → ∀(v : Type) → Map k v+    = λ(k : Type) → λ(v : Type) → [] : Map k v++let example0 =+      assert : empty Text Bool ≡ ([] : List { mapKey : Text, mapValue : Bool })++in  empty
+ dhall-lang/Prelude/Map/keyText view
@@ -0,0 +1,3 @@+  missing+    sha256:f7b6c802ca5764d03d5e9a6e48d9cb167c01392f775d9c2c87b83cdaa60ea0cc+? ./keyText.dhall
+ dhall-lang/Prelude/Map/keyText.dhall view
@@ -0,0 +1,15 @@+{-|+Builds a key-value record such that a `List` of them will be converted to a+homogeneous record by dhall-to-json and dhall-to-yaml.++Both key and value are fixed to `Text`.++Take a look at `./keyValue` for a polymorphic version.+-}+let keyText =+      λ(key : Text) → λ(value : Text) → { mapKey = key, mapValue = value }++let example0 =+      assert : keyText "foo" "bar" ≡ { mapKey = "foo", mapValue = "bar" }++in  keyText
+ dhall-lang/Prelude/Map/keyValue view
@@ -0,0 +1,3 @@+  missing+    sha256:a0a97199d280c4cce72ffcbbf93b7ceda0a569cf4d173ac98e0aaaa78034b98c+? ./keyValue.dhall
+ dhall-lang/Prelude/Map/keyValue.dhall view
@@ -0,0 +1,17 @@+{-|+Builds a key-value record such that a List of them will be converted to a+homogeneous record by dhall-to-json and dhall-to-yaml.+-}+let keyValue =+      λ(v : Type) →+      λ(key : Text) →+      λ(value : v) →+        { mapKey = key, mapValue = value }++let example0 =+      assert : keyValue Natural "foo" 2 ≡ { mapKey = "foo", mapValue = 2 }++let example1 =+      assert : keyValue Text "bar" "baz" ≡ { mapKey = "bar", mapValue = "baz" }++in  keyValue
+ dhall-lang/Prelude/Map/keys view
@@ -0,0 +1,3 @@+  missing+    sha256:d13ec34e6acf7c349d82272ef09a37c7bdf37f0dab489e9df47a1ff215d9f5e7+? ./keys.dhall
+ dhall-lang/Prelude/Map/keys.dhall view
@@ -0,0 +1,39 @@+--| Get all of the keys of a `Map` as a `List`+let Map =+        missing+          sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed+      ? ./Type.dhall++let Entry =+        missing+          sha256:f334283bdd9cd88e6ea510ca914bc221fc2dab5fb424d24514b2e0df600d5346+      ? ./Entry.dhall++let List/map =+        missing+          sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+      ? ../List/map++let keys+    : ∀(k : Type) → ∀(v : Type) → Map k v → List k+    = λ(k : Type) →+      λ(v : Type) →+        List/map (Entry k v) k (λ(x : Entry k v) → x.mapKey)++let example0 =+        assert+      :   keys+            Text+            Natural+            [ { mapKey = "A", mapValue = 2 }+            , { mapKey = "B", mapValue = 3 }+            , { mapKey = "C", mapValue = 5 }+            ]+        ≡ [ "A", "B", "C" ]++let example1 =+        assert+      :   keys Text Natural ([] : List { mapKey : Text, mapValue : Natural })+        ≡ ([] : List Text)++in  keys
+ dhall-lang/Prelude/Map/map view
@@ -0,0 +1,3 @@+  missing+    sha256:23e09b0b9f08649797dfe1ca39755d5e1c7cad2d0944bdd36c7a0bf804bde8d0+? ./map.dhall
+ dhall-lang/Prelude/Map/map.dhall view
@@ -0,0 +1,58 @@+--| Transform a `Map` by applying a function to each value+let Map =+        missing+          sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed+      ? ./Type.dhall++let Entry =+        missing+          sha256:f334283bdd9cd88e6ea510ca914bc221fc2dab5fb424d24514b2e0df600d5346+      ? ./Entry.dhall++let List/map =+        missing+          sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+      ? ../List/map.dhall++let map+    : ∀(k : Type) → ∀(a : Type) → ∀(b : Type) → (a → b) → Map k a → Map k b+    = λ(k : Type) →+      λ(a : Type) →+      λ(b : Type) →+      λ(f : a → b) →+      λ(m : Map k a) →+        List/map+          (Entry k a)+          (Entry k b)+          ( λ(before : Entry k a) →+              { mapKey = before.mapKey, mapValue = f before.mapValue }+          )+          m++let example0 =+        assert+      :   map+            Text+            Natural+            Bool+            Natural/even+            [ { mapKey = "A", mapValue = 2 }+            , { mapKey = "B", mapValue = 3 }+            , { mapKey = "C", mapValue = 5 }+            ]+        ≡ [ { mapKey = "A", mapValue = True }+          , { mapKey = "B", mapValue = False }+          , { mapKey = "C", mapValue = False }+          ]++let example1 =+        assert+      :   map+            Text+            Natural+            Bool+            Natural/even+            ([] : List { mapKey : Text, mapValue : Natural })+        ≡ ([] : List { mapKey : Text, mapValue : Bool })++in  map
+ dhall-lang/Prelude/Map/mapMaybe.dhall view
@@ -0,0 +1,56 @@+--| Apply a function across the values of a `Map k v`, dropping+--  entries whose values return `None`.+let Map/empty =+        missing+          sha256:4c612558b8bbe8f955550ed3fb295d57b1b864c85cd52615b52d0ee0e9682e52+      ? ./empty.dhall++let Map/unpackOptionals =+        missing+          sha256:66c3e6f6f81418cf99342e1dba739617c01af4b27c1ca5e2e1d7bce64a522e22+      ? ./unpackOptionals.dhall++let Map/map =+        missing+          sha256:23e09b0b9f08649797dfe1ca39755d5e1c7cad2d0944bdd36c7a0bf804bde8d0+      ? ./map.dhall++let Map/Type =+        missing+          sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed+      ? ./Type.dhall++let mapMaybe+    : ∀(k : Type) →+      ∀(a : Type) →+      ∀(b : Type) →+      (a → Optional b) →+      Map/Type k a →+        Map/Type k b+    = λ(k : Type) →+      λ(a : Type) →+      λ(b : Type) →+      λ(f : a → Optional b) →+      λ(m : Map/Type k a) →+        Map/unpackOptionals k b (Map/map k a (Optional b) f m)++let property =+      λ(k : Type) →+      λ(a : Type) →+      λ(b : Type) →+      λ(f : a → Optional b) →+        assert : mapMaybe k a b f (Map/empty k a) ≡ Map/empty k b++let example0 =+        assert+      :   mapMaybe+            Text+            Natural+            Text+            ( λ(n : Natural) →+                if Natural/isZero n then None Text else Some (Natural/show n)+            )+            (toMap { foo = 2, bar = 0 })+        ≡ toMap { foo = "2" }++in  mapMaybe
+ dhall-lang/Prelude/Map/package.dhall view
@@ -0,0 +1,41 @@+{ Type =+      missing+        sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed+    ? ./Type+, Entry =+      missing+        sha256:f334283bdd9cd88e6ea510ca914bc221fc2dab5fb424d24514b2e0df600d5346+    ? ./Entry+, empty =+      missing+        sha256:4c612558b8bbe8f955550ed3fb295d57b1b864c85cd52615b52d0ee0e9682e52+    ? ./empty+, keyText =+      missing+        sha256:f7b6c802ca5764d03d5e9a6e48d9cb167c01392f775d9c2c87b83cdaa60ea0cc+    ? ./keyText+, keyValue =+      missing+        sha256:a0a97199d280c4cce72ffcbbf93b7ceda0a569cf4d173ac98e0aaaa78034b98c+    ? ./keyValue+, keys =+      missing+        sha256:d13ec34e6acf7c349d82272ef09a37c7bdf37f0dab489e9df47a1ff215d9f5e7+    ? ./keys+, map =+      missing+        sha256:23e09b0b9f08649797dfe1ca39755d5e1c7cad2d0944bdd36c7a0bf804bde8d0+    ? ./map+, mapMaybe =+      missing+        sha256:4ea58b720d7af38cef3ef07bef36e476caeed21032cd4a9dc733868a74d9a521+    ? ./mapMaybe.dhall+, unpackOptionals =+      missing+        sha256:66c3e6f6f81418cf99342e1dba739617c01af4b27c1ca5e2e1d7bce64a522e22+    ? ./unpackOptionals.dhall+, values =+      missing+        sha256:ae02cfb06a9307cbecc06130e84fd0c7b96b7f1f11648961e1b030ec00940be8+    ? ./values+}
+ dhall-lang/Prelude/Map/unpackOptionals.dhall view
@@ -0,0 +1,41 @@+--| Turn a `Map k (Optional v)` into a `Map k v` by dropping all+--  entries with value `None`.+let List/concatMap =+        missing+          sha256:3b2167061d11fda1e4f6de0522cbe83e0d5ac4ef5ddf6bb0b2064470c5d3fb64+      ? ../List/concatMap.dhall++let Map/Entry =+        missing+          sha256:f334283bdd9cd88e6ea510ca914bc221fc2dab5fb424d24514b2e0df600d5346+      ? ./Entry.dhall++let Map/Type =+        missing+          sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed+      ? ./Type.dhall++let unpackOptionals+    : ∀(k : Type) → ∀(v : Type) → Map/Type k (Optional v) → Map/Type k v+    = λ(k : Type) →+      λ(v : Type) →+        List/concatMap+          (Map/Entry k (Optional v))+          (Map/Entry k v)+          ( λ(e : Map/Entry k (Optional v)) →+              merge+                { None = [] : Map/Type k v+                , Some = λ(v : v) → [ { mapKey = e.mapKey, mapValue = v } ]+                }+                e.mapValue+          )++let example0 =+        assert+      :   unpackOptionals+            Text+            Text+            (toMap { foo = Some "bar", baz = None Text })+        ≡ toMap { foo = "bar" }++in  unpackOptionals
+ dhall-lang/Prelude/Map/values view
@@ -0,0 +1,3 @@+  missing+    sha256:ae02cfb06a9307cbecc06130e84fd0c7b96b7f1f11648961e1b030ec00940be8+? ./values.dhall
+ dhall-lang/Prelude/Map/values.dhall view
@@ -0,0 +1,39 @@+--| Get all of the values of a `Map` as a `List`+let Map =+        missing+          sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed+      ? ./Type.dhall++let Entry =+        missing+          sha256:f334283bdd9cd88e6ea510ca914bc221fc2dab5fb424d24514b2e0df600d5346+      ? ./Entry.dhall++let List/map =+        missing+          sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+      ? ../List/map.dhall++let values+    : ∀(k : Type) → ∀(v : Type) → Map k v → List v+    = λ(k : Type) →+      λ(v : Type) →+        List/map (Entry k v) v (λ(x : Entry k v) → x.mapValue)++let example0 =+        assert+      :   values+            Text+            Natural+            [ { mapKey = "A", mapValue = 2 }+            , { mapKey = "B", mapValue = 3 }+            , { mapKey = "C", mapValue = 5 }+            ]+        ≡ [ 2, 3, 5 ]++let example1 =+        assert+      :   values Text Natural ([] : List { mapKey : Text, mapValue : Natural })+        ≡ ([] : List Natural)++in  values
dhall-lang/Prelude/Monoid view
@@ -1,39 +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`--Examples:--```-./build-(   λ(natural : Type)-→   λ(succ : natural → natural)-→   λ(zero : natural)-→   succ (succ (succ zero))-)-= 3--./build-(   λ(natural : Type)-→   λ(succ : natural → natural)-→   λ(zero : natural)-→   zero-)-= 0-```--}-let build-    :   (   ∀(natural : Type)-          → ∀(succ : natural → natural)-          → ∀(zero : natural)-          → natural-        )-      → Natural-    = Natural/build--in  build+  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,36 +1,3 @@-{--Generate a list of numbers from `0` up to but not including the specified-number--Examples:--```-./enumerate 10 = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]--./enumerate 0 = [] : List Natural-```--}-let enumerate-    : Natural → List Natural-    =   λ(n : Natural)-      → List/build-        Natural-        (   λ(list : Type)-          → λ(cons : Natural → list → list)-          → List/fold-            { index : Natural, value : {} }-            ( List/indexed-              {}-              ( List/build-                {}-                (   λ(list : Type)-                  → λ(cons : {} → list → list)-                  → Natural/fold n list (cons {=})-                )-              )-            )-            list-            (λ(x : { index : Natural, value : {} }) → cons x.index)-        )--in  enumerate+  missing+    sha256:0cf083980a752b21ce0df9fc2222a4c139f50909e2353576e26a191002aa1ce3+? ./enumerate.dhall
+ dhall-lang/Prelude/Natural/enumerate.dhall view
@@ -0,0 +1,32 @@+{-|+Generate a list of numbers from `0` up to but not including the specified+number+-}+let enumerate+    : Natural → List Natural+    = λ(n : Natural) →+        List/build+          Natural+          ( λ(list : Type) →+            λ(cons : Natural → list → list) →+              List/fold+                { index : Natural, value : {} }+                ( List/indexed+                    {}+                    ( List/build+                        {}+                        ( λ(list : Type) →+                          λ(cons : {} → list → list) →+                            Natural/fold n list (cons {=})+                        )+                    )+                )+                list+                (λ(x : { index : Natural, value : {} }) → cons x.index)+          )++let example0 = assert : enumerate 10 ≡ [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]++let example1 = assert : enumerate 0 ≡ ([] : List Natural)++in  enumerate
+ dhall-lang/Prelude/Natural/equal view
@@ -0,0 +1,3 @@+  missing+    sha256:7f108edfa35ddc7cebafb24dc073478e93a802e13b5bc3fd22f4768c9b066e60+? ./equal.dhall
+ dhall-lang/Prelude/Natural/equal.dhall view
@@ -0,0 +1,17 @@+--| `equal` checks if two Naturals are equal.+let lessThanEqual =+        missing+          sha256:1a5caa2b80a42b9f58fff58e47ac0d9a9946d0b2d36c54034b8ddfe3cb0f3c99+      ? ./lessThanEqual.dhall++let equal+    : Natural → Natural → Bool+    = λ(a : Natural) → λ(b : Natural) → lessThanEqual a b && lessThanEqual b a++let example0 = assert : equal 5 5 ≡ True++let example1 = assert : equal 5 6 ≡ False++let property0 = λ(n : Natural) → assert : equal n n ≡ True++in  equal
dhall-lang/Prelude/Natural/even view
@@ -1,12 +1,3 @@-{--Returns `True` if a number if even and returns `False` otherwise--Examples:--```-./even 3 = False--./even 0 = True-```--}-let even : Natural → Bool = Natural/even in even+  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,33 +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--Examples:--```-./fold 3 Natural (λ(x : Natural) → 5 * x) 1 = 125--λ(zero : Natural) → ./fold 3 Natural (λ(x : Natural) → 5 * x) zero-= λ(zero : Natural) → 5 * (5 * (5 * zero))--    λ(natural : Type)-→   λ(succ : natural → natural)-→   λ(zero : natural)-→   ./fold 3 natural succ zero-=   λ(natural : Type)-→   λ(succ : natural → natural)-→   λ(zero : natural)-→   succ (succ (succ zero))-```--}-let fold-    :   Natural-      → ∀(natural : Type)-      → ∀(succ : natural → natural)-      → ∀(zero : natural)-      → natural-    = Natural/fold--in  fold+  missing+    sha256:fd01c931e585a8f5fd049af7b076b862ea164f1813b34800c7616a49e549ee06+? ./fold.dhall
+ dhall-lang/Prelude/Natural/fold.dhall view
@@ -0,0 +1,28 @@+{-|+`fold` is the primitive function for consuming `Natural` numbers++If you treat the number `3` as `succ (succ (succ zero))` then a `fold` just+replaces each `succ` and `zero` with something else+-}+let fold+    : Natural →+      ∀(natural : Type) →+      ∀(succ : natural → natural) →+      ∀(zero : natural) →+        natural+    = Natural/fold++let example0 = assert : fold 3 Text (λ(x : Text) → "A" ++ x) "B" ≡ "AAAB"++let example1 =+      λ(zero : Text) →+          assert+        :   fold 3 Text (λ(x : Text) → "A" ++ x) zero+          ≡ "A" ++ ("A" ++ ("A" ++ zero))++let example2 =+      λ(succ : Text → Text) →+      λ(zero : Text) →+        assert : fold 3 Text succ zero ≡ succ (succ (succ zero))++in  fold
+ dhall-lang/Prelude/Natural/greaterThan view
@@ -0,0 +1,3 @@+  missing+    sha256:f702abcdfcd7ad73619b9285d7e41c3a1d017fb6b8d037cf40bd93bf30c09b2c+? ./greaterThan.dhall
+ dhall-lang/Prelude/Natural/greaterThan.dhall view
@@ -0,0 +1,21 @@+--| `greaterThan` checks if one Natural is strictly greater than another.+let lessThan =+        missing+          sha256:3381b66749290769badf8855d8a3f4af62e8de52d1364d838a9d1e20c94fa70c+      ? ./lessThan.dhall++let greaterThan+    : Natural → Natural → Bool+    = λ(x : Natural) → λ(y : Natural) → lessThan y x++let example0 = assert : greaterThan 5 6 ≡ False++let example1 = assert : greaterThan 5 5 ≡ False++let example2 = assert : greaterThan 5 4 ≡ True++let property0 = λ(n : Natural) → assert : greaterThan 0 n ≡ False++let property1 = λ(n : Natural) → assert : greaterThan n n ≡ False++in  greaterThan
+ dhall-lang/Prelude/Natural/greaterThanEqual view
@@ -0,0 +1,3 @@+  missing+    sha256:30ebfab0febd7aa0ccccfdf3dc36ee6d50f0117f35dd4a9b034750b7e885a1a4+? ./greaterThanEqual.dhall
+ dhall-lang/Prelude/Natural/greaterThanEqual.dhall view
@@ -0,0 +1,23 @@+{-|+`greaterThanEqual` checks if one Natural is greater than or equal to another.+-}+let lessThanEqual =+        missing+          sha256:1a5caa2b80a42b9f58fff58e47ac0d9a9946d0b2d36c54034b8ddfe3cb0f3c99+      ? ./lessThanEqual.dhall++let greaterThanEqual+    : Natural → Natural → Bool+    = λ(x : Natural) → λ(y : Natural) → lessThanEqual y x++let example0 = assert : greaterThanEqual 5 6 ≡ False++let example1 = assert : greaterThanEqual 5 5 ≡ True++let example2 = assert : greaterThanEqual 5 4 ≡ True++let property0 = λ(n : Natural) → assert : greaterThanEqual n 0 ≡ True++let property1 = λ(n : Natural) → assert : greaterThanEqual n n ≡ True++in  greaterThanEqual
dhall-lang/Prelude/Natural/isZero view
@@ -1,12 +1,3 @@-{--Returns `True` if a number is `0` and returns `False` otherwise--Examples:--```-./isZero 2 = False--./isZero 0 = True-```--}-let isZero : Natural → Bool = Natural/isZero in isZero+  missing+    sha256:1be98236800ed2d5cff44f16ca02b34b0c37dfa239d9e0d63d9d2c6eeae3d1d1+? ./isZero.dhall
+ dhall-lang/Prelude/Natural/isZero.dhall view
@@ -0,0 +1,10 @@+--| Returns `True` if a number is `0` and returns `False` otherwise+let isZero+    : Natural → Bool+    = Natural/isZero++let example0 = assert : isZero 2 ≡ False++let example1 = assert : isZero 0 ≡ True++in  isZero
+ dhall-lang/Prelude/Natural/lessThan view
@@ -0,0 +1,3 @@+  missing+    sha256:3381b66749290769badf8855d8a3f4af62e8de52d1364d838a9d1e20c94fa70c+? ./lessThan.dhall
+ dhall-lang/Prelude/Natural/lessThan.dhall view
@@ -0,0 +1,26 @@+--| `lessThan` checks if one Natural is strictly less than another.+let greaterThanEqual =+        missing+          sha256:30ebfab0febd7aa0ccccfdf3dc36ee6d50f0117f35dd4a9b034750b7e885a1a4+      ? ./greaterThanEqual.dhall++let Bool/not =+        missing+          sha256:723df402df24377d8a853afed08d9d69a0a6d86e2e5b2bac8960b0d4756c7dc4+      ? ../Bool/not.dhall++let lessThan+    : Natural → Natural → Bool+    = λ(x : Natural) → λ(y : Natural) → Bool/not (greaterThanEqual x y)++let example0 = assert : lessThan 5 6 ≡ True++let example1 = assert : lessThan 5 5 ≡ False++let example2 = assert : lessThan 5 4 ≡ False++let property0 = λ(n : Natural) → assert : lessThan n 0 ≡ False++let property1 = λ(n : Natural) → assert : lessThan n n ≡ False++in  lessThan
+ dhall-lang/Prelude/Natural/lessThanEqual view
@@ -0,0 +1,3 @@+  missing+    sha256:1a5caa2b80a42b9f58fff58e47ac0d9a9946d0b2d36c54034b8ddfe3cb0f3c99+? ./lessThanEqual.dhall
+ dhall-lang/Prelude/Natural/lessThanEqual.dhall view
@@ -0,0 +1,16 @@+--| `lessThanEqual` checks if one Natural is less than or equal to another.+let lessThanEqual+    : Natural → Natural → Bool+    = λ(x : Natural) → λ(y : Natural) → Natural/isZero (Natural/subtract y x)++let example0 = assert : lessThanEqual 5 6 ≡ True++let example1 = assert : lessThanEqual 5 5 ≡ True++let example2 = assert : lessThanEqual 5 4 ≡ False++let property0 = λ(n : Natural) → assert : lessThanEqual 0 n ≡ True++let property1 = λ(n : Natural) → assert : lessThanEqual n n ≡ True++in  lessThanEqual
+ dhall-lang/Prelude/Natural/listMax view
@@ -0,0 +1,3 @@+  missing+    sha256:20906ffcc9970f740106d4516cb7868b43d75ff8c9f00ff8a9680ae68c48a472+? ./listMax.dhall
+ dhall-lang/Prelude/Natural/listMax.dhall view
@@ -0,0 +1,30 @@+{-|+`listMax` returns the largest element of a `List` or `None Natural` if the+`List` is empty+-}+let max =+        missing+          sha256:1f3b18da330223ab039fad11693da72c7e68d516f50502c73f41a89a097b62f7+      ? ./max.dhall++let Optional/map =+        missing+          sha256:501534192d988218d43261c299cc1d1e0b13d25df388937add784778ab0054fa+      ? ../Optional/map.dhall++let listMax+    : List Natural → Optional Natural+    = λ(xs : List Natural) →+        Optional/map+          Natural+          Natural+          (λ(n : Natural) → List/fold Natural xs Natural max n)+          (List/head Natural xs)++let example0 = assert : listMax [ 1, 2 ] ≡ Some 2++let example1 = assert : listMax ([] : List Natural) ≡ None Natural++let property0 = λ(n : Natural) → assert : listMax [ n ] ≡ Some n++in  listMax
+ dhall-lang/Prelude/Natural/listMin view
@@ -0,0 +1,3 @@+  missing+    sha256:ee70b0d010bbca6012162e8ae1f6e9d9bd10a152675509b0f23145b98b5d43c6+? ./listMin.dhall
+ dhall-lang/Prelude/Natural/listMin.dhall view
@@ -0,0 +1,34 @@+{-|+`listMin` returns the smallest element of a `List` or `None Natural` if the+`List` is empty+-}+let min =+        missing+          sha256:f25f9c462e4dbf0eb15f9ff6ac840c6e9c82255a7f4f2ab408bdab338e028710+      ? ./min.dhall++let Optional/map =+        missing+          sha256:501534192d988218d43261c299cc1d1e0b13d25df388937add784778ab0054fa+      ? ../Optional/map.dhall++let listMin+    : List Natural → Optional Natural+    = λ(xs : List Natural) →+        Optional/map+          Natural+          Natural+          ( λ(n : Natural) →+              if Natural/isZero n then n else List/fold Natural xs Natural min n+          )+          (List/head Natural xs)++let example0 = assert : listMin [ 0, 1 ] ≡ Some 0++let example1 = assert : listMin ([] : List Natural) ≡ None Natural++let example2 = assert : listMin [ 3, 2, 1 ] ≡ Some 1++let property0 = λ(n : Natural) → assert : listMin [ n ] ≡ Some n++in  listMin
+ dhall-lang/Prelude/Natural/max view
@@ -0,0 +1,3 @@+  missing+    sha256:1f3b18da330223ab039fad11693da72c7e68d516f50502c73f41a89a097b62f7+? ./max.dhall
+ dhall-lang/Prelude/Natural/max.dhall view
@@ -0,0 +1,19 @@+--| `max a b` returns the larger of `a` or `b`+let lessThanEqual =+        missing+          sha256:1a5caa2b80a42b9f58fff58e47ac0d9a9946d0b2d36c54034b8ddfe3cb0f3c99+      ? ./lessThanEqual.dhall++let max+    : Natural → Natural → Natural+    = λ(a : Natural) → λ(b : Natural) → if lessThanEqual a b then b else a++let example0 = assert : max 1 2 ≡ 2++let example1 = assert : max 2 1 ≡ 2++let property0 = λ(n : Natural) → assert : max n n ≡ n++let property1 = λ(n : Natural) → assert : max 0 n ≡ n++in  max
+ dhall-lang/Prelude/Natural/min view
@@ -0,0 +1,3 @@+  missing+    sha256:f25f9c462e4dbf0eb15f9ff6ac840c6e9c82255a7f4f2ab408bdab338e028710+? ./min.dhall
+ dhall-lang/Prelude/Natural/min.dhall view
@@ -0,0 +1,17 @@+--| `min a b` returns the smaller of `a` or `b`+let lessThanEqual =+        missing+          sha256:1a5caa2b80a42b9f58fff58e47ac0d9a9946d0b2d36c54034b8ddfe3cb0f3c99+      ? ./lessThanEqual.dhall++let min+    : Natural → Natural → Natural+    = λ(a : Natural) → λ(b : Natural) → if lessThanEqual a b then a else b++let example0 = assert : min 1 2 ≡ 1++let example1 = assert : min 2 1 ≡ 1++let property0 = λ(n : Natural) → assert : min n n ≡ n++in  min
dhall-lang/Prelude/Natural/odd view
@@ -1,12 +1,3 @@-{--Returns `True` if a number is odd and returns `False` otherwise--Examples:--```-./odd 3 = True--./odd 0 = False-```--}-let odd : Natural → Bool = Natural/odd in odd+  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,34 +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 =+      missing+        sha256:3381b66749290769badf8855d8a3f4af62e8de52d1364d838a9d1e20c94fa70c+    ? ./lessThan.dhall+, lessThanEqual =+      missing+        sha256:1a5caa2b80a42b9f58fff58e47ac0d9a9946d0b2d36c54034b8ddfe3cb0f3c99+    ? ./lessThanEqual.dhall+, equal =+      missing+        sha256:7f108edfa35ddc7cebafb24dc073478e93a802e13b5bc3fd22f4768c9b066e60+    ? ./equal.dhall+, greaterThanEqual =+      missing+        sha256:30ebfab0febd7aa0ccccfdf3dc36ee6d50f0117f35dd4a9b034750b7e885a1a4+    ? ./greaterThanEqual.dhall+, greaterThan =+      missing+        sha256:f702abcdfcd7ad73619b9285d7e41c3a1d017fb6b8d037cf40bd93bf30c09b2c+    ? ./greaterThan.dhall+, min =+      missing+        sha256:f25f9c462e4dbf0eb15f9ff6ac840c6e9c82255a7f4f2ab408bdab338e028710+    ? ./min.dhall+, max =+      missing+        sha256:1f3b18da330223ab039fad11693da72c7e68d516f50502c73f41a89a097b62f7+    ? ./max.dhall+, listMin =+      missing+        sha256:ee70b0d010bbca6012162e8ae1f6e9d9bd10a152675509b0f23145b98b5d43c6+    ? ./listMin.dhall+, listMax =+      missing+        sha256:20906ffcc9970f740106d4516cb7868b43d75ff8c9f00ff8a9680ae68c48a472+    ? ./listMax.dhall+, sort =+      missing+        sha256:36ce8b3e5538454763987ca904d8d7c5ba34c2147434a19eddd51f684432b260+    ? ./sort.dhall+, subtract =+      missing+        sha256:b9277ac637d09142a3a3ac79137ef5955c42f8b33b6746d59db2c9d75ccdd745+    ? ./subtract.dhall }
dhall-lang/Prelude/Natural/product view
@@ -1,17 +1,3 @@-{--Multiply all the numbers in a `List`--Examples:--```-./product [ 2, 3, 5 ] = 30--./product ([] : List Natural) = 1-```--}-let product-    : List Natural → Natural-    =   λ(xs : List Natural)-      → List/fold Natural xs Natural (λ(l : Natural) → λ(r : Natural) → l * r) 1--in  product+  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)--Examples:--```-./show 3 = "3"--./show 0 = "0"-```--}-let show : Natural → Text = Natural/show 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
@@ -0,0 +1,3 @@+  missing+    sha256:36ce8b3e5538454763987ca904d8d7c5ba34c2147434a19eddd51f684432b260+? ./sort.dhall
+ dhall-lang/Prelude/Natural/sort.dhall view
@@ -0,0 +1,61 @@+--| `sort` sorts a `List` of `Natural`s in ascending order+let greaterThanEqual =+        missing+          sha256:30ebfab0febd7aa0ccccfdf3dc36ee6d50f0117f35dd4a9b034750b7e885a1a4+      ? ./greaterThanEqual.dhall++let listMin =+        missing+          sha256:ee70b0d010bbca6012162e8ae1f6e9d9bd10a152675509b0f23145b98b5d43c6+      ? ./listMin.dhall++let List/partition =+        missing+          sha256:38147ac6d750a6492736dd90cc967bf09aa405c499de943c64fab7b86ae02f03+      ? ../List/partition.dhall++let Accumulator = { sorted : List Natural, rest : List Natural }++let partitionMinima =+      λ(xs : List Natural) →+        merge+          { Some =+              λ(m : Natural) → List/partition Natural (greaterThanEqual m) xs+          , None = { true = [] : List Natural, false = [] : List Natural }+          }+          (listMin xs)++let test0 =+        assert+      : partitionMinima [ 2, 1, 1, 3 ] ≡ { true = [ 1, 1 ], false = [ 2, 3 ] }++let step =+      λ(x : Accumulator) →+        let p = partitionMinima x.rest++        in  { sorted = x.sorted # p.true, rest = p.false }++let test1 =+        assert+      :   step { sorted = [ 1, 1 ], rest = [ 2, 3 ] }+        ≡ { sorted = [ 1, 1, 2 ], rest = [ 3 ] }++let sort+    : List Natural → List Natural+    = λ(xs : List Natural) →+        let x =+              Natural/fold+                (List/length Natural xs)+                Accumulator+                step+                { sorted = [] : List Natural, rest = xs }++        in  x.sorted++let example0 = assert : sort ([] : List Natural) ≡ ([] : List Natural)++let example1 = assert : sort [ 1 ] ≡ [ 1 ]++let example2 = assert : sort [ 3, 2, 1, 3, 2, 1 ] ≡ [ 1, 1, 2, 2, 3, 3 ]++in  sort
+ dhall-lang/Prelude/Natural/subtract view
@@ -0,0 +1,3 @@+  missing+    sha256:b9277ac637d09142a3a3ac79137ef5955c42f8b33b6746d59db2c9d75ccdd745+? ./subtract.dhall
+ dhall-lang/Prelude/Natural/subtract.dhall view
@@ -0,0 +1,18 @@+--| `subtract m n` computes `n - m`, truncating to `0` if `m > n`+let subtract+    : Natural → Natural → Natural+    = Natural/subtract++let example0 = assert : subtract 1 2 ≡ 1++let example1 = assert : subtract 1 1 ≡ 0++let example2 = assert : subtract 2 1 ≡ 0++let property0 = λ(n : Natural) → assert : subtract 0 n ≡ n++let property1 = λ(n : Natural) → assert : subtract n 0 ≡ 0++let property2 = λ(n : Natural) → assert : subtract n n ≡ 0++in  subtract
dhall-lang/Prelude/Natural/sum view
@@ -1,17 +1,3 @@-{--Add all the numbers in a `List`--Examples:--```-./sum [ 2, 3, 5 ] = 10--./sum ([] : List Natural) = 0-```--}-let sum-    : List Natural → Natural-    =   λ(xs : List Natural)-      → List/fold Natural xs Natural (λ(l : Natural) → λ(r : Natural) → l + r) 0--in  sum+  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,16 +1,3 @@-{--Convert a `Natural` number to the corresponding `Double`--Examples:--```-./toDouble 3 = 3.0--./toDouble 0 = 0.0-```--}-let toDouble-    : Natural → Double-    = λ(n : Natural) → Integer/toDouble (Natural/toInteger n)--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`--Examples:--```-./toInteger 3 = +3--./toInteger 0 = +0-```--}-let toInteger : Natural → Integer = Natural/toInteger 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,20 +1,3 @@-{--Returns `False` if the supplied function returns `False` for a present element-and `True` otherwise:--Examples:--```-./all Natural Natural/even (Some 3) = False--./all Natural Natural/even (None Natural) = True-```--}-let all-    : ∀(a : Type) → (a → Bool) → Optional a → Bool-    =   λ(a : Type)-      → λ(f : a → Bool)-      → λ(xs : Optional a)-      → Optional/fold a xs Bool f True--in  all+  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,20 +1,3 @@-{--Returns `True` if the supplied function returns `True` for a present element and-`False` otherwise--Examples:--```-./any Natural Natural/even (Some 2) = True--./any Natural Natural/even (None Natural) = False-```--}-let any-    : ∀(a : Type) → (a → Bool) → Optional a → Bool-    =   λ(a : Type)-      → λ(f : a → Bool)-      → λ(xs : Optional a)-      → Optional/fold a xs Bool f False--in  any+  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,36 +1,3 @@-{--`build` is the inverse of `fold`--Examples:--```-./build-Natural-(   λ(optional : Type)-→   λ(some : Natural → optional)-→   λ(none : optional)-→   some 1-)-= Some 1--./build-Natural-(   λ(optional : Type)-→   λ(some : Natural → optional)-→   λ(none : optional)-→   none-)-= None Natural-```--}-let build-    :   ∀(a : Type)-      → (   ∀(optional : Type)-          → ∀(some : a → optional)-          → ∀(none : optional)-          → optional-        )-      → Optional a-    = Optional/build--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,28 +1,3 @@-{--Flatten two `Optional` layers into a single `Optional` layer--Examples:--```-./concat Natural (Some (Some 1))-= Some 1--./concat Natural (Some (None Natural))-= None Natural--./concat Natural (None (Optional Natural))-= None Natural-```--}-let concat-    : ∀(a : Type) → Optional (Optional a) → Optional a-    =   λ(a : Type)-      → λ(x : Optional (Optional a))-      → Optional/fold-        (Optional a)-        x-        (Optional a)-        (λ(y : Optional a) → y)-        (None a)--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
@@ -0,0 +1,3 @@+  missing+    sha256:5bd665b0d6605c374b3c4a7e2e2bd3b9c1e39323d41441149ed5e30d86e889ad+? ./default.dhall
+ dhall-lang/Prelude/Optional/default.dhall view
@@ -0,0 +1,13 @@+--| Unpack an `Optional`, returning the default when it's `None`.+let default+    : ∀(a : Type) → a → Optional a → a+    = λ(a : Type) →+      λ(default : a) →+      λ(o : Optional a) →+        merge { Some = λ(x : a) → x, None = default } o++let example0 = assert : default Bool False (None Bool) ≡ False++let example1 = assert : default Bool False (Some True) ≡ True++in  default
+ dhall-lang/Prelude/Optional/equal.dhall view
@@ -0,0 +1,24 @@+let Optional/fold =+        missing+          sha256:c5b9d72f6f62bdaa0e196ac1c742cc175cd67a717b880fb8aec1333a5a4132cf+      ? ./fold.dhall++let Optional/null =+        missing+          sha256:3871180b87ecaba8b53fffb2a8b52d3fce98098fab09a6f759358b9e8042eedc+      ? ./null.dhall++let equal+    : forall (a : Type) -> (a -> a -> Bool) -> Optional a -> Optional a -> Bool+    = \(a : Type) ->+      \(compare : a -> a -> Bool) ->+      \(ox : Optional a) ->+      \(oy : Optional a) ->+        Optional/fold+          a+          ox+          Bool+          (\(x : a) -> Optional/fold a oy Bool (compare x) False)+          (Optional/null a oy)++in  equal
dhall-lang/Prelude/Optional/filter view
@@ -1,32 +1,3 @@-{--Only keep an `Optional` element if the supplied function returns `True`--Examples:--```-./filter Natural Natural/even (Some 2)-= Some 2--./filter Natural Natural/odd (Some 2)-= None Natural-```--}-let filter-    : ∀(a : Type) → (a → Bool) → Optional a → Optional a-    =   λ(a : Type)-      → λ(f : a → Bool)-      → λ(xs : Optional a)-      → Optional/build-        a-        (   λ(optional : Type)-          → λ(some : a → optional)-          → λ(none : optional)-          → Optional/fold-            a-            xs-            optional-            (λ(x : a) → if f x then some x else none)-            none-        )--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,21 +1,3 @@-{--`fold` is the primitive function for consuming `Optional` values--Examples:--```-./fold Natural (Some 2) Natural (λ(x : Natural) → x) 0 = 2--./fold Natural (None Natural) Natural (λ(x : Natural) → x) 0 = 0-```--}-let fold-    :   ∀(a : Type)-      → Optional a-      → ∀(optional : Type)-      → ∀(some : a → optional)-      → ∀(none : optional)-      → optional-    = Optional/fold--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,28 +1,3 @@-{--Returns the first non-empty `Optional` value in a `List`--Examples:--```-./head Natural [ None Natural, Some 1, Some 2 ] = Some 1--./head Natural [ None Natural, None Natural ] = None Natural--./head Natural ([] : List (Optional Natural)) = None Natural-```--}-let head-    : ∀(a : Type) → List (Optional a) → Optional a-    =   λ(a : Type)-      → λ(xs : List (Optional a))-      → List/fold-        (Optional a)-        xs-        (Optional a)-        (   λ(l : Optional a)-          → λ(r : Optional a)-          → Optional/fold a l (Optional a) (λ(x : a) → Some x) r-        )-        (None a)--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,28 +1,3 @@-{--Returns the last non-empty `Optional` value in a `List`--Examples:--```-./last Natural [ None Natural, Some 1, Some 2 ] = Some 2--./last Natural [ None Natural, None Natural ] = None Natural--./last Natural ([] : List (Optional Natural)) = None Natural-```--}-let last-    : ∀(a : Type) → List (Optional a) → Optional a-    =   λ(a : Type)-      → λ(xs : List (Optional a))-      → List/fold-        (Optional a)-        xs-        (Optional a)-        (   λ(l : Optional a)-          → λ(r : Optional a)-          → Optional/fold a r (Optional a) (λ(x : a) → Some x) l-        )-        (None a)--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,18 +1,3 @@-{--Returns `1` if the `Optional` value is present and `0` if the value is absent--Examples:--```-./length Natural (Some 2) = 1--./length Natural (None Natural) = 0-```--}-let length-    : ∀(a : Type) → Optional a → Natural-    =   λ(a : Type)-      → λ(xs : Optional a)-      → Optional/fold a xs Natural (λ(_ : a) → 1) 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,20 +1,3 @@-{--Transform an `Optional` value with a function--Examples:--```-./map Natural Bool Natural/even (Some 3) = Some False--./map Natural Bool Natural/even (None Natural) = None Bool-```--}-let map-    : ∀(a : Type) → ∀(b : Type) → (a → b) → Optional a → Optional b-    =   λ(a : Type)-      → λ(b : Type)-      → λ(f : a → b)-      → λ(o : Optional a)-      → Optional/fold a o (Optional b) (λ(x : a) → Some (f x)) (None b)--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,18 +1,3 @@-{--Returns `True` if the `Optional` value is absent and `False` if present--Examples:--```-./null Natural (Some 2) = False--./null Natural (None Natural) = True-```--}-let null-    : ∀(a : Type) → Optional a → Bool-    =   λ(a : Type)-      → λ(xs : Optional a)-      → Optional/fold a xs Bool (λ(_ : a) → False) 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,40 +1,65 @@ { all =-      ./all sha256:b9b015fe8be14da940901aa1510ee1d5e205df37ee651c32ac975a799782c410-    ? ./all+      missing+        sha256:a303004b6def0a2a05bf5f0a8d54e84dd45d8bef581789186ac04924956a1695+    ? ./all.dhall , any =-      ./any sha256:0a637c0f2cc7d30b8f0bca021d2ee1ad1213fb9d9712c669b29feab66a590eaf-    ? ./any+      missing+        sha256:96a5cf4f31b3c598b09161dd3082f0a09f4328a4cefda6a7e09894b37b17b435+    ? ./any.dhall , build =-      ./build sha256:f331299d1279cfb88dd25a5acfdd64130900991b6154239ad343a2883f6eb50c-    ? ./build+      missing+        sha256:28e61294bf2dd59dc57cf74f719d1568e60b5ba46c28eac586bc937eff4a2af1+    ? ./build.dhall , concat =-      ./concat sha256:b49a3b7dc49eb83d150977caa5ae347be1cbbe14e3b6d0e07349bd2e5f707d69-    ? ./concat+      missing+        sha256:b7736bd3ebeab14c3912dfb534d0c970a025b001d06c2d5461d4b0e289e3cb7a+    ? ./concat.dhall+, concatMap =+      missing+        sha256:c06ae93e900a99299c9b4ec4912ca5395a0103ea88292205b08dd7e345632818+    ? ./concatMap.dhall+, default =+      missing+        sha256:5bd665b0d6605c374b3c4a7e2e2bd3b9c1e39323d41441149ed5e30d86e889ad+    ? ./default.dhall+, equal =+      missing+        sha256:5411888399fe9c6720f7f3b59caf5eff3e8e8c30402d09f34e46a4457649a35a+    ? ./equal.dhall , filter =-      ./filter sha256:b3d5e19a6cec592a76c12167a9e5e1e76649e776229d70a11c77b76cd29f617e-    ? ./filter+      missing+        sha256:54f0a487d578801819613fe000050c038c632edf1f9ccc57677e98ae0ef56b83+    ? ./filter.dhall , fold =-      ./fold sha256:62139ff410ca84302acebe763a8a1794420dd472d907384c7fb80df2a2180302-    ? ./fold+      missing+        sha256:c5b9d72f6f62bdaa0e196ac1c742cc175cd67a717b880fb8aec1333a5a4132cf+    ? ./fold.dhall , head =-      ./head sha256:b0b5d257294515f1de35f24fa83e54d7f1d5ebca9c3c1fc903a80ab40e19b3a6-    ? ./head+      missing+        sha256:4f256c9338b60a1933f41f2a8fafd861930a1e41770a644cdbac0622676fa34c+    ? ./head.dhall , last =-      ./last sha256:f839221a8a04adae6c501458eb264e7f4e375a1facb294cb80caacfd012a6765-    ? ./last+      missing+        sha256:50400771ae19e9b75efa6581feec318ae1ade0b6a60e215df428c66c4b052707+    ? ./last.dhall , length =-      ./length sha256:722a3754a411c053f006a32c506a6d1b14869c2ab799169df9cdac346edf07d3-    ? ./length+      missing+        sha256:f168337c5244ded68c05ecf32ce068b6b87158881d07e87b8cb6853fc6982a85+    ? ./length.dhall , map =-      ./map sha256:e7f44219250b89b094fbf9996e04b5daafc0902d864113420072ae60706ac73d-    ? ./map+      missing+        sha256:501534192d988218d43261c299cc1d1e0b13d25df388937add784778ab0054fa+    ? ./map.dhall , null =-      ./null sha256:efc43103e49b56c5bf089db8e0365bbfc455b8a2f0dc6ee5727a3586f85969fd-    ? ./null+      missing+        sha256:3871180b87ecaba8b53fffb2a8b52d3fce98098fab09a6f759358b9e8042eedc+    ? ./null.dhall , toList =-      ./toList sha256:390fe99619e9a25e71a253a2b33011f9e5fa26a7d990795205543d1edd72ce5b-    ? ./toList+      missing+        sha256:d78f160c619119ef12389e48a629ce293d69f7624c8d016b7a4767ab400344c4+    ? ./toList.dhall , unzip =-      ./unzip sha256:7b517bc2a8a4dbec044c6bea5e059cafde5a0cb1d3a5e7d13d346c9327a00f30-    ? ./unzip+      missing+        sha256:d016c01ba91657a2f35609aa29087963d0f506bab0f41d5e8b7cd289dff39708+    ? ./unzip.dhall }
dhall-lang/Prelude/Optional/toList view
@@ -1,18 +1,3 @@-{--Convert an `Optional` value into the equivalent `List`--Examples:--```-./toList Natural (Some 1) = [ 1 ]--./toList Natural (None Natural) = [] : List Natural-```--}-let toList-    : ∀(a : Type) → Optional a → List a-    =   λ(a : Type)-      → λ(o : Optional a)-      → Optional/fold a o (List a) (λ(x : a) → [ x ] : List a) ([] : List a)--in  toList+  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,38 +1,3 @@-{--Unzip an `Optional` value into two separate `Optional` values--Examples:--```-./unzip Text Bool (Some { _1 = "ABC", _2 = True  })-= { _1 = Some "ABC", _2 = Some True }--./unzip Text Bool (None { _1 : Text, _2 : Bool })-= { _1 = None Text, _2 = None Bool }-```--}-let unzip-    :   ∀(a : Type)-      → ∀(b : Type)-      → Optional { _1 : a, _2 : b }-      → { _1 : Optional a, _2 : Optional b }-    =   λ(a : Type)-      → λ(b : Type)-      → λ(xs : Optional { _1 : a, _2 : b })-      → { _1 =-            Optional/fold-            { _1 : a, _2 : b }-            xs-            (Optional a)-            (λ(x : { _1 : a, _2 : b }) → Some x._1)-            (None a)-        , _2 =-            Optional/fold-            { _1 : a, _2 : b }-            xs-            (Optional b)-            (λ(x : { _1 : a, _2 : b }) → Some x._2)-            (None b)-        }--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,17 +1,3 @@-{--Concatenate all the `Text` values in a `List`--Examples:--```-./concat [ "ABC", "DEF", "GHI" ] = "ABCDEFGHI"--./concat ([] : List Text) = ""-```--}-let concat-    : List Text → Text-    =   λ(xs : List Text)-      → List/fold Text xs Text (λ(x : Text) → λ(y : Text) → x ++ y) ""--in  concat+  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,21 +1,3 @@-{--Transform each value in a `List` into `Text` and concatenate the result--Examples:--```-./concatMap Natural (λ(n : Natural) → "${Natural/show n} ") [ 0, 1, 2 ]-= "0 1 2 "--./concatMap Natural (λ(n : Natural) → "${Natural/show n} ") ([] : List Natural)-= ""-```--}-let concatMap-    : ∀(a : Type) → (a → Text) → List a → Text-    =   λ(a : Type)-      → λ(f : a → Text)-      → λ(xs : List a)-      → List/fold a xs Text (λ(x : a) → λ(y : Text) → f x ++ y) ""--in  concatMap+  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,41 +1,3 @@-{--Transform each value in a `List` to `Text` and then concatenate them with a-separator in between each value--Examples:--```-./concatMapSep ", " Natural Natural/show [ 0, 1, 2 ] = "0, 1, 2"--./concatMapSep ", " Natural Natural/show ([] : List Natural) = ""-```--}-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--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,38 +1,3 @@-{--Concatenate a `List` of `Text` values with a separator in between each value--Examples:--```-./concatSep ", " [ "ABC", "DEF", "GHI" ] = "ABC, DEF, GHI"--./concatSep ", " ([] : List Text) = ""-```--}-let 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--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
@@ -0,0 +1,3 @@+  missing+    sha256:f532c8891b1e427d90a6cc07cf7e793a4c84b0765e1bfe69f186ee2ec91c1edf+? ./default.dhall
+ dhall-lang/Prelude/Text/default.dhall view
@@ -0,0 +1,10 @@+--| Unwrap an `Optional` `Text` value, defaulting `None` to `""`+let default+    : Optional Text → Text+    = λ(o : Optional Text) → merge { Some = λ(t : Text) → t, None = "" } o++let example0 = assert : default (Some "ABC") ≡ "ABC"++let example1 = assert : default (None Text) ≡ ""++in  default
+ dhall-lang/Prelude/Text/defaultMap view
@@ -0,0 +1,3 @@+  missing+    sha256:3a3fa1264f6198800c27483cb144de2c5366484876d60b9c739a710ce0288588+? ./defaultMap.dhall
+ dhall-lang/Prelude/Text/defaultMap.dhall view
@@ -0,0 +1,13 @@+--| Transform the value in an `Optional` into `Text`, defaulting `None` to `""`+let defaultMap+    : ∀(a : Type) → (a → Text) → Optional a → Text+    = λ(a : Type) →+      λ(f : a → Text) →+      λ(o : Optional a) →+        merge { Some = f, None = "" } o++let example0 = assert : defaultMap Natural Natural/show (Some 0) ≡ "0"++let example1 = assert : defaultMap Natural Natural/show (None Natural) ≡ ""++in  defaultMap
+ dhall-lang/Prelude/Text/lowerASCII.dhall view
@@ -0,0 +1,56 @@+{-|+Lowercase all ASCII characters++Note that this will also lowercase decomposed Unicode characters that contain+codepoints in the ASCII range+-}+let lowerASCII+    : Text → Text+    = List/fold+        (Text → Text)+        [ Text/replace "A" "a"+        , Text/replace "B" "b"+        , Text/replace "C" "c"+        , Text/replace "D" "d"+        , Text/replace "E" "e"+        , Text/replace "F" "f"+        , Text/replace "G" "g"+        , Text/replace "H" "h"+        , Text/replace "I" "i"+        , Text/replace "J" "j"+        , Text/replace "K" "k"+        , Text/replace "L" "l"+        , Text/replace "M" "m"+        , Text/replace "N" "n"+        , Text/replace "O" "o"+        , Text/replace "P" "p"+        , Text/replace "Q" "q"+        , Text/replace "R" "r"+        , Text/replace "S" "s"+        , Text/replace "T" "t"+        , Text/replace "U" "u"+        , Text/replace "V" "v"+        , Text/replace "W" "w"+        , Text/replace "X" "x"+        , Text/replace "Y" "y"+        , Text/replace "Z" "z"+        ]+        Text+        (λ(replacement : Text → Text) → replacement)++let example0 = assert : lowerASCII "ABCdef" ≡ "abcdef"++let -- This does not lowercase precomposed Unicode characters+    --+    -- • The `Á` in the following example is U+00C1+    example1 =+      assert : lowerASCII "Á" ≡ "Á"++let -- … but this does lowercase decomposed Unicode characters+    --+    -- • The `Á` in the following example is U+0041 U+0301+    -- • The `á` in the following example is U+0061 U+0301+    example1 =+      assert : lowerASCII "Á" ≡ "á"++in  lowerASCII
dhall-lang/Prelude/Text/package.dhall view
@@ -1,16 +1,53 @@ { concat =-      ./concat sha256:35e20d9403fbadb1a0061edb84e076ed56313709fa4bc8124d86ff54896f20ac-    ? ./concat+      missing+        sha256:731265b0288e8a905ecff95c97333ee2db614c39d69f1514cb8eed9259745fc0+    ? ./concat.dhall , concatMap =-      ./concatMap sha256:175d893ad7f2b2c05fff9e32f0d9cbadc7f5fce57945071508cf3603f8aa298e-    ? ./concatMap+      missing+        sha256:7a0b0b99643de69d6f94ba49441cd0fa0507cbdfa8ace0295f16097af37e226f+    ? ./concatMap.dhall , concatMapSep =-      ./concatMapSep sha256:46b81a9e211fb8278bf2793e75e8175fef79e0e3e478ef1016e3233ecc2ddfe6-    ? ./concatMapSep+      missing+        sha256:c272aca80a607bc5963d1fcb38819e7e0d3e72ac4d02b1183b1afb6a91340840+    ? ./concatMapSep.dhall , concatSep =-      ./concatSep sha256:d28e61f5057a240e857e09dba1b040fa3477bddb9659c5606c760852a9165890-    ? ./concatSep+      missing+        sha256:e4401d69918c61b92a4c0288f7d60a6560ca99726138ed8ebc58dca2cd205e58+    ? ./concatSep.dhall+, default =+      missing+        sha256:f532c8891b1e427d90a6cc07cf7e793a4c84b0765e1bfe69f186ee2ec91c1edf+    ? ./default.dhall+, defaultMap =+      missing+        sha256:3a3fa1264f6198800c27483cb144de2c5366484876d60b9c739a710ce0288588+    ? ./defaultMap.dhall+, lowerASCII =+      missing+        sha256:26b076651120b907e869396bd3dc16271f2e12433062b2f26f296968a69515e7+    ? ./lowerASCII.dhall+, replace =+      missing+        sha256:7d132df0e091a43817bba8afa06d1bb487ee51c091430404ad6f8c78bc0328a6+    ? ./replace.dhall+, replicate =+      missing+        sha256:1b398b1d464b3a6c7264a690ac3cacb443b5683b43348c859d68e7c2cb925c4f+    ? ./replicate.dhall+, shell-escape =+      missing+        sha256:d53521b3f478cb18a7d63730bc0e3153c2124b70d6ac9a1f610ce7db67cfc7a2+    ? ./shell-escape.dhall , show =-      ./show sha256:c9dc5de3e5f32872dbda57166804865e5e80785abe358ff61f1d8ac45f1f4784-    ? ./show+      missing+        sha256:c9dc5de3e5f32872dbda57166804865e5e80785abe358ff61f1d8ac45f1f4784+    ? ./show.dhall+, spaces =+      missing+        sha256:fccfd4f26601e006bf6a79ca948dbd37c676cdd0db439554447320293d23b3dc+    ? ./spaces.dhall+, upperASCII =+      missing+        sha256:45ae4fbd814b0474e65c28a4ee92b23b979892fa5bb73730bc99675ae790ca29+    ? ./upperASCII.dhall }
+ dhall-lang/Prelude/Text/replace.dhall view
@@ -0,0 +1,14 @@+{-+Replace a section of `Text` with another inside a `Text` literal.+-}+let replace+    : ∀(needle : Text) → ∀(replacement : Text) → ∀(haystack : Text) → Text+    = Text/replace++let example0 = assert : replace "-" "_" "foo-bar" ≡ "foo_bar"++let example1 = assert : replace "💣" "💥" "💣💣💣" ≡ "💥💥💥"++let example2 = assert : replace "👨" "👩" "👨‍👩‍👧‍👦" ≡ "👩‍👩‍👧‍👦"++in  replace
+ dhall-lang/Prelude/Text/replicate view
@@ -0,0 +1,3 @@+  missing+    sha256:1b398b1d464b3a6c7264a690ac3cacb443b5683b43348c859d68e7c2cb925c4f+? ./replicate.dhall
+ dhall-lang/Prelude/Text/replicate.dhall view
@@ -0,0 +1,20 @@+--| Build a Text by copying the given Text the specified number of times+let concat =+        missing+          sha256:731265b0288e8a905ecff95c97333ee2db614c39d69f1514cb8eed9259745fc0+      ? ./concat.dhall++let List/replicate =+        missing+          sha256:d4250b45278f2d692302489ac3e78280acb238d27541c837ce46911ff3baa347+      ? ../List/replicate.dhall++let replicate+    : Natural → Text → Text+    = λ(num : Natural) → λ(text : Text) → concat (List/replicate num Text text)++let example0 = assert : replicate 3 "foo" ≡ "foofoofoo"++let property = λ(text : Text) → assert : replicate 0 text ≡ ""++in  replicate
+ dhall-lang/Prelude/Text/shell-escape.dhall view
@@ -0,0 +1,16 @@+{-|+Escape a Text value such that it can be used safely in shells.+The escaping is done by replacing all `'` with `'"'"'` and wraps that string in+single quotes.++This works for all POSIX-compliant shells and some other shells like csh.+-}+let shell-escape+    : Text -> Text+    = \(xs : Text) -> "'${Text/replace "'" "'\"'\"'" xs}'"++let example0 = assert : shell-escape "foo" === "'foo'"++let example1 = assert : shell-escape "foo'bar" === "'foo'\"'\"'bar'"++in  shell-escape
dhall-lang/Prelude/Text/show view
@@ -1,13 +1,3 @@-{--Render a `Text` literal as its own representation as Dhall source code (i.e. a-double-quoted string literal)--Examples:--```-./show "ABC" = "\"ABC\""--./show "\u0000 \$ \\ \n \u263a" = "\"\\u0000 \\u0024 \\\\ \\n ☺\""-```--}-let show : Text → Text = Text/show 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
@@ -0,0 +1,3 @@+  missing+    sha256:fccfd4f26601e006bf6a79ca948dbd37c676cdd0db439554447320293d23b3dc+? ./spaces.dhall
+ dhall-lang/Prelude/Text/spaces.dhall view
@@ -0,0 +1,20 @@+{-|+Return a Text with the number of spaces specified.++This function is particularly helpful when trying to generate Text where+whitespace is significant, i.e. with nested indentation.+-}+let replicate =+        missing+          sha256:1b398b1d464b3a6c7264a690ac3cacb443b5683b43348c859d68e7c2cb925c4f+      ? ./replicate.dhall++let spaces+    : Natural → Text+    = λ(a : Natural) → replicate a " "++let example0 = assert : spaces 1 ≡ " "++let example1 = assert : spaces 0 ≡ ""++in  spaces
+ dhall-lang/Prelude/Text/upperASCII.dhall view
@@ -0,0 +1,56 @@+{-|+Uppercase all ASCII characters++Note that this will also uppercase decomposed Unicode characters that contain+codepoints in the ASCII range+-}+let upperASCII+    : Text → Text+    = List/fold+        (Text → Text)+        [ Text/replace "a" "A"+        , Text/replace "b" "B"+        , Text/replace "c" "C"+        , Text/replace "d" "D"+        , Text/replace "e" "E"+        , Text/replace "f" "F"+        , Text/replace "g" "G"+        , Text/replace "h" "H"+        , Text/replace "i" "I"+        , Text/replace "j" "J"+        , Text/replace "k" "K"+        , Text/replace "l" "L"+        , Text/replace "m" "M"+        , Text/replace "n" "N"+        , Text/replace "o" "O"+        , Text/replace "p" "P"+        , Text/replace "q" "Q"+        , Text/replace "r" "R"+        , Text/replace "s" "S"+        , Text/replace "t" "T"+        , Text/replace "u" "U"+        , Text/replace "v" "V"+        , Text/replace "w" "W"+        , Text/replace "x" "X"+        , Text/replace "y" "Y"+        , Text/replace "z" "Z"+        ]+        Text+        (λ(replacement : Text → Text) → replacement)++let example0 = assert : upperASCII "ABCdef" ≡ "ABCDEF"++let -- This does not uppercase precomposed Unicode characters+    --+    -- • The `á` in the following example is U+00E1+    example1 =+      assert : upperASCII "á" ≡ "á"++let -- … but this does uppercase decomposed Unicode characters+    --+    -- • The `Á` in the following example is U+0041 U+0301+    -- • The `á` in the following example is U+0061 U+0301+    example1 =+      assert : upperASCII "á" ≡ "Á"++in  upperASCII
+ dhall-lang/Prelude/Time/package.dhall view
@@ -0,0 +1,5 @@+{ show =+      missing+        sha256:8cabfe35dd0ee25ca65708105e860cbf4b789e0d73134aa905580799e2a46719+    ? ./show.dhall+}
+ dhall-lang/Prelude/Time/show.dhall view
@@ -0,0 +1,15 @@+{-+Render a `Time` as `Text` using the same representation as Dhall source code+(i.e. `hh:mm:ss`)+-}+let show+    : Time → Text+    = Time/show++let example0 = assert : show 03:15:47.90 ≡ "03:15:47.90"++let example1 = assert : show 00:00:00 ≡ "00:00:00"++let example2 = assert : show 11:59:59 ≡ "11:59:59"++in  show
+ dhall-lang/Prelude/TimeZone/package.dhall view
@@ -0,0 +1,5 @@+{ show =+      missing+        sha256:d183361f1c4c656bad3b170ec8b8d6705f564faebf94e4ef10c76061104ff061+    ? ./show.dhall+}
+ dhall-lang/Prelude/TimeZone/show.dhall view
@@ -0,0 +1,15 @@+{-+Render a `TimeZone` as `Text` using the same representation as Dhall source code+(i.e. `±HH:MM`)+-}+let show+    : TimeZone → Text+    = TimeZone/show++let example0 = assert : show +07:00 ≡ "+07:00"++let example1 = assert : show +00:00 ≡ "+00:00"++let example2 = assert : show -05:00 ≡ "-05:00"++in  show
+ dhall-lang/Prelude/XML/Type view
@@ -0,0 +1,3 @@+  missing+    sha256:ab91a0edaf0513e0083b1dfae5efa160adc99b0e589775a4a699ab77cce528a9+? ./Type.dhall
+ dhall-lang/Prelude/XML/Type.dhall view
@@ -0,0 +1,65 @@+{-|+Dhall encoding of an arbitrary XML element++For example, the following XML element:++```+<foo n="1"><bar>baz</bar></foo>+```++... corresponds to the following Dhall expression:+++```+λ(XML : Type)+ → λ ( xml+     : { text :+           Text → XML+       , rawText :+           Text → XML+       , element :+             { attributes :+                 List { mapKey : Text, mapValue : Text }+             , content :+                 List XML+             , name :+                 Text+             }+           → XML+       }+     )+ → xml.element+   { attributes =+       [ { mapKey = "n", mapValue = "1" } ]+   , content =+       [ xml.element+         { attributes =+             [] : List { mapKey : Text, mapValue : Text }+         , content =+             [ xml.text "baz" ]+         , name =+             "bar"+         }+       ]+   , name =+       "foo"+   }+```+-}+let XML/Type+    : Type+    = ∀(XML : Type) →+      ∀ ( xml+        : { text : Text → XML+          , rawText : Text → XML+          , element :+              { attributes : List { mapKey : Text, mapValue : Text }+              , content : List XML+              , name : Text+              } →+                XML+          }+        ) →+        XML++in  XML/Type
+ dhall-lang/Prelude/XML/attribute view
@@ -0,0 +1,3 @@+  missing+    sha256:f7b6c802ca5764d03d5e9a6e48d9cb167c01392f775d9c2c87b83cdaa60ea0cc+? ./attribute.dhall
+ dhall-lang/Prelude/XML/attribute.dhall view
@@ -0,0 +1,6 @@+--| Builds a key-value record with a Text key and value.+let attribute+    : Text → Text → { mapKey : Text, mapValue : Text }+    = λ(key : Text) → λ(value : Text) → { mapKey = key, mapValue = value }++in  attribute
+ dhall-lang/Prelude/XML/element view
@@ -0,0 +1,3 @@+  missing+    sha256:79266d604e147caf37e985581523b684f7bac66de0c93dd828841df3dfc445f9+? ./element.dhall
+ dhall-lang/Prelude/XML/element.dhall view
@@ -0,0 +1,59 @@+{-|+Create an XML element value.++```+let XML = ./package.dhall++in  XML.render+    ( XML.element+      { name = "foo"+      , attributes = XML.emptyAttributes+      , content =+          [ XML.leaf { name = "bar", attributes = [ XML.attribute "n" "1" ] }+          , XML.leaf { name = "baz", attributes = [ XML.attribute "n" "2" ] }+          ]+      }+    )++= "<foo><bar n=\"1\"/><baz n=\"2\"/></foo>"+```+-}+let XML =+        missing+          sha256:ab91a0edaf0513e0083b1dfae5efa160adc99b0e589775a4a699ab77cce528a9+      ? ./Type.dhall++let List/map =+        missing+          sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+      ? ../List/map.dhall++let Args =+        { attributes : List { mapKey : Text, mapValue : Text }+        , name : Text+        , content : List XML+        }+      : Type++let element+    : Args → XML+    = λ(elem : Args) →+      λ(XML : Type) →+      λ ( xml+        : { text : Text → XML+          , rawText : Text → XML+          , element :+              { attributes : List { mapKey : Text, mapValue : Text }+              , content : List XML+              , name : Text+              } →+                XML+          }+        ) →+        xml.element+          { attributes = elem.attributes+          , name = elem.name+          , content = List/map XML@1 XML (λ(x : XML@1) → x XML xml) elem.content+          }++in  element
+ dhall-lang/Prelude/XML/emptyAttributes view
@@ -0,0 +1,3 @@+  missing+    sha256:11b86e2d3f3c75d47a1d580213d2a03fd2c36d64f3e9b6381de0ba23472f64d5+? ./emptyAttributes.dhall
+ dhall-lang/Prelude/XML/emptyAttributes.dhall view
@@ -0,0 +1,2 @@+--| Create an empty XML attribute List.+[] : List { mapKey : Text, mapValue : Text }
+ dhall-lang/Prelude/XML/leaf view
@@ -0,0 +1,3 @@+  missing+    sha256:5dcedf79a3664a362479f470220bb2f4932facde657c285fd8a3c24ab137c506+? ./leaf.dhall
+ dhall-lang/Prelude/XML/leaf.dhall view
@@ -0,0 +1,30 @@+{-|+Create an XML element value without child elements.++```+let XML = ./package.dhall++in  XML.render (XML.leaf { name = "foobar", attributes = XML.emptyAttributes })++= "<foobar/>"+```+-}+let XML =+        missing+          sha256:ab91a0edaf0513e0083b1dfae5efa160adc99b0e589775a4a699ab77cce528a9+      ? ./Type.dhall++let element =+        missing+          sha256:79266d604e147caf37e985581523b684f7bac66de0c93dd828841df3dfc445f9+      ? ./element.dhall++let leaf+    : { attributes : List { mapKey : Text, mapValue : Text }, name : Text } →+        XML+    = λ ( elem+        : { attributes : List { mapKey : Text, mapValue : Text }, name : Text }+        ) →+        element (elem ⫽ { content = [] : List XML })++in  leaf
+ dhall-lang/Prelude/XML/package.dhall view
@@ -0,0 +1,33 @@+{ Type =+      missing+        sha256:ab91a0edaf0513e0083b1dfae5efa160adc99b0e589775a4a699ab77cce528a9+    ? ./Type.dhall+, attribute =+      missing+        sha256:f7b6c802ca5764d03d5e9a6e48d9cb167c01392f775d9c2c87b83cdaa60ea0cc+    ? ./attribute.dhall+, render =+      missing+        sha256:395c293702c85d99f6f2b461f3eee320f9fe5749c320c2e8b9ea799a7d210b66+    ? ./render.dhall+, element =+      missing+        sha256:79266d604e147caf37e985581523b684f7bac66de0c93dd828841df3dfc445f9+    ? ./element.dhall+, leaf =+      missing+        sha256:5dcedf79a3664a362479f470220bb2f4932facde657c285fd8a3c24ab137c506+    ? ./leaf.dhall+, text =+      missing+        sha256:a59670560a08bfc815893dee1f3eae21a5252400f8a619d1cd7bdd9f48eea2ab+    ? ./text.dhall+, rawText =+      missing+        sha256:2af9d72c151677d4110039e361b7e9faaf2947e6c9d29aa72aea351ad797e05d+    ? ./rawText.dhall+, emptyAttributes =+      missing+        sha256:11b86e2d3f3c75d47a1d580213d2a03fd2c36d64f3e9b6381de0ba23472f64d5+    ? ./emptyAttributes.dhall+}
+ dhall-lang/Prelude/XML/rawText.dhall view
@@ -0,0 +1,40 @@+{-|+Create a Text value to be inserted into an XML element as content with no+character escaping.++```+let XML = ./package.dhall++in  XML.render+    ( XML.element+      { name = "location"+      , attributes = XML.emptyAttributes+      , content = [ XML.rawText "<bar n=\"1\"/>" ]+      }+    )+= "<foo><bar n=\"1\"/></foo>"+```+-}+let XML =+        missing+          sha256:ab91a0edaf0513e0083b1dfae5efa160adc99b0e589775a4a699ab77cce528a9+      ? ./Type.dhall++let rawText+    : Text → XML+    = λ(d : Text) →+      λ(XML : Type) →+      λ ( xml+        : { text : Text → XML+          , rawText : Text → XML+          , element :+              { attributes : List { mapKey : Text, mapValue : Text }+              , content : List XML+              , name : Text+              } →+                XML+          }+        ) →+        xml.rawText d++in  rawText
+ dhall-lang/Prelude/XML/render view
@@ -0,0 +1,3 @@+  missing+    sha256:395c293702c85d99f6f2b461f3eee320f9fe5749c320c2e8b9ea799a7d210b66+? ./render.dhall
+ dhall-lang/Prelude/XML/render.dhall view
@@ -0,0 +1,140 @@+{-|+Render an `XML` value as `Text`++For indentation and schema validation, see the `xmllint` utility+bundled with libxml2.++```+let XML = ./package.dhall++in  XML.render+    ( XML.element+      { name = "foo"+      , attributes = [ XML.attribute "a" "x", XML.attribute "b" (Natural/show 2) ]+      , content = [ XML.leaf { name = "bar", attributes = XML.emptyAttributes } ]+      }+    )+= "<foo a=\"x\" b=\"2\"><bar/></foo>"+```++-}+let XML =+        missing+          sha256:ab91a0edaf0513e0083b1dfae5efa160adc99b0e589775a4a699ab77cce528a9+      ? ./Type.dhall++let Text/concatMap =+        missing+          sha256:7a0b0b99643de69d6f94ba49441cd0fa0507cbdfa8ace0295f16097af37e226f+      ? ../Text/concatMap.dhall++let Text/concat =+        missing+          sha256:731265b0288e8a905ecff95c97333ee2db614c39d69f1514cb8eed9259745fc0+      ? ../Text/concat.dhall++let element =+        missing+          sha256:79266d604e147caf37e985581523b684f7bac66de0c93dd828841df3dfc445f9+      ? ./element.dhall++let text =+        missing+          sha256:a59670560a08bfc815893dee1f3eae21a5252400f8a619d1cd7bdd9f48eea2ab+      ? ./text.dhall++let emptyAttributes =+        missing+          sha256:11b86e2d3f3c75d47a1d580213d2a03fd2c36d64f3e9b6381de0ba23472f64d5+      ? ./emptyAttributes.dhall++let Attr = { mapKey : Text, mapValue : Text }++let esc = λ(x : Text) → λ(y : Text) → Text/replace x "&${y};"++let `escape&` = esc "&" "amp"++let `escape<` = esc "<" "lt"++let `escape>` = esc ">" "gt"++let `escape'` = esc "'" "apos"++let `escape"` = esc "\"" "quot"++let escapeCommon = λ(text : Text) → `escape<` (`escape&` text)++let escapeAttr = λ(text : Text) → `escape"` (`escape'` (escapeCommon text))++let escapeText = λ(text : Text) → `escape>` (escapeCommon text)++let renderAttr = λ(x : Attr) → " ${x.mapKey}=\"${escapeAttr x.mapValue}\""++let render+    : XML → Text+    = λ(x : XML) →+        x+          Text+          { text = escapeText+          , rawText = λ(t : Text) → t+          , element =+              λ ( elem+                : { attributes : List { mapKey : Text, mapValue : Text }+                  , content : List Text+                  , name : Text+                  }+                ) →+                let attribs = Text/concatMap Attr renderAttr elem.attributes++                in      "<${elem.name}${attribs}"+                    ++  ( if    Natural/isZero (List/length Text elem.content)+                          then  "/>"+                          else  ">${Text/concat elem.content}</${elem.name}>"+                        )+          }++let simple =+      λ(name : Text) →+      λ(content : List XML) →+        element { name, attributes = emptyAttributes, content }++let example0 =+        assert+      :   render+            ( simple+                "note"+                [ simple "to" [ text "Tove" ]+                , simple "from" [ text "Jani" ]+                , simple "heading" [ text "Reminder" ]+                , simple "body" [ text "Don't forget me this weekend!" ]+                ]+            )+        ≡ Text/replace+            "\n"+            ""+            ''+            <note>+            <to>Tove</to>+            <from>Jani</from>+            <heading>Reminder</heading>+            <body>Don't forget me this weekend!</body>+            </note>+            ''++let example1 =+        assert+      :   render+            ( element+                { name = "escape"+                , attributes = toMap { attribute = "<>'\"&" }+                , content = [ text "<>'\"&" ]+                }+            )+        ≡ Text/replace+            "\n"+            ""+            ''+            <escape attribute="&lt;>&apos;&quot;&amp;">&lt;&gt;'"&amp;</escape>+            ''++in  render
+ dhall-lang/Prelude/XML/text view
@@ -0,0 +1,3 @@+  missing+    sha256:a59670560a08bfc815893dee1f3eae21a5252400f8a619d1cd7bdd9f48eea2ab+? ./text.dhall
+ dhall-lang/Prelude/XML/text.dhall view
@@ -0,0 +1,39 @@+{-|+Create a Text value to be inserted into an XML element as content.++```+let XML = ./package.dhall++in  XML.render+    ( XML.element+      { name = "location"+      , attributes = XML.emptyAttributes+      , content = [ XML.text "/foo/bar" ]+      }+    )+= "<location>/foo/bar</location>"+```+-}+let XML =+        missing+          sha256:ab91a0edaf0513e0083b1dfae5efa160adc99b0e589775a4a699ab77cce528a9+      ? ./Type.dhall++let text+    : Text → XML+    = λ(d : Text) →+      λ(XML : Type) →+      λ ( xml+        : { text : Text → XML+          , rawText : Text → XML+          , element :+              { attributes : List { mapKey : Text, mapValue : Text }+              , content : List XML+              , name : Text+              } →+                XML+          }+        ) →+        xml.text d++in  text
dhall-lang/Prelude/package.dhall view
@@ -1,28 +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:74c3822b98b9d37f9f820af8e1a7ee790bcfac03050eabd45af4a255fb93e026+      missing+        sha256:f4ca848f69034f9d7a74e12c556c3a3396966c1de3a9427a102d1aff4580192f     ? ./Function/package.dhall , Integer =-      ./Integer/package.dhall sha256:eb464566d3192dd16ce915a9bd874aaaad612d5c69beb356e5b7d2e0c4949dcf+      missing+        sha256:d1a572ca3a764781496847e4921d7d9a881c18ffcfac6ae28d0e5299066938a0     ? ./Integer/package.dhall+, JSON =+      missing+        sha256:5f98b7722fd13509ef448b075e02b9ff98312ae7a406cf53ed25012dbc9990ac+    ? ./JSON/package.dhall , List =-      ./List/package.dhall sha256:108be3af5ebd465f7091039f2216c433e65ae5d25556a9a71786dd84d33ef49a+      missing+        sha256:26d1b4cd800219d8b67043c638926aa6e5517ea74a0bd3e371974514621bca04     ? ./List/package.dhall+, Location =+      missing+        sha256:0eb4e4a60814018009c720f6820aaa13cf9491eb1b09afb7b832039c6ee4d470+    ? ./Location/package.dhall+, Map =+      missing+        sha256:c5e79a9de642644a09b96a2ec3147c5d8662b7926f09610e751c0c0f6ed0b30a+    ? ./Map/package.dhall+, Monoid =+      missing+        sha256:26fafa098600ef7a54ef9dba5ada416bbbdd21df1af306c052420c61553ad4af+    ? ./Monoid.dhall , Natural =-      ./Natural/package.dhall sha256:fe08155c3a04500df847ca94d013ecd3dfc73ab5c136109b2414fce3ec42b63a+      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:36a366af67a3c26cd5d196e095d3023f18953c5b5db3a03956fa554609e5442a+      missing+        sha256:74331dfe59c09db65edc7ec4498bff92473c8c06d92752f9470d26e25f91320c     ? ./Optional/package.dhall-, JSON =-      ./JSON/package.dhall sha256:7f0c25a292e5d34ddfbbf3f6d90505567382f95d822b04f5810745f81ab1ef35-    ? ./JSON/package.dhall , Text =-      ./Text/package.dhall sha256:c8bc93456397476051dc674c180ddd5db098546861c8df24bda8284511d3305e+      missing+        sha256:79b671a70ac459b799a53bbb8a383cc8b81b40421745c54bf0fb1143168cbd6f     ? ./Text/package.dhall+, Time =+      missing+        sha256:6715c4c71a113429fef8b94e4561a93c288942dad9dfd75ac545de96c5b5652a+    ? ./Time/package.dhall+, TimeZone =+      missing+        sha256:c17fd403c637856f34c8287168b92974e8c1a3a7331967f75276d179057084fd+    ? ./TimeZone/package.dhall+, XML =+      missing+        sha256:2e111f0952087d42072b059f0bf4c95861a46bffa67ad4c8c39086edf405f32e+    ? ./XML/package.dhall }
+ dhall-lang/tests/alpha-normalization/success/regression/preludeBoolFoldA.dhall view
@@ -0,0 +1,6 @@+-- For https://github.com/dhall-lang/dhall-haskell/issues/929+  λ(b : Bool)+→ λ(bool : Type)+→ λ(true : bool)+→ λ(false : bool)+→ if b then true else false
+ dhall-lang/tests/alpha-normalization/success/regression/preludeBoolFoldB.dhall view
@@ -0,0 +1,1 @@+λ(_ : Bool) → λ(_ : Type) → λ(_ : _) → λ(_ : _@1) → if _@3 then _@1 else _
dhall-lang/tests/alpha-normalization/success/unit/FunctionBindingUnderscoreA.dhall view
@@ -1,1 +1,1 @@-λ(_ : A) → b+λ(_ : Bool) → _
dhall-lang/tests/alpha-normalization/success/unit/FunctionBindingUnderscoreB.dhall view
@@ -1,1 +1,1 @@-λ(_ : A) → b+λ(_ : Bool) → _
dhall-lang/tests/alpha-normalization/success/unit/FunctionBindingXA.dhall view
@@ -1,1 +1,1 @@-λ(x : A) → x+λ(x : Bool) → x
dhall-lang/tests/alpha-normalization/success/unit/FunctionBindingXB.dhall view
@@ -1,1 +1,1 @@-λ(_ : A) → _+λ(_ : Bool) → _
dhall-lang/tests/alpha-normalization/success/unit/FunctionNestedBindingXA.dhall view
@@ -1,1 +1,1 @@-λ(x : A) → λ(_ : B) → x+λ(x : Bool) → λ(_ : Natural) → x
dhall-lang/tests/alpha-normalization/success/unit/FunctionNestedBindingXB.dhall view
@@ -1,1 +1,1 @@-λ(_ : A) → λ(_ : B) → _@1+λ(_ : Bool) → λ(_ : Natural) → _@1
dhall-lang/tests/alpha-normalization/success/unit/FunctionNestedBindingXXB.dhall view
@@ -1,1 +1,1 @@-\(_: Bool) -> \(_: Bool) -> _ && _@1+λ(_ : Bool) → λ(_ : Bool) → _ && _@1
dhall-lang/tests/alpha-normalization/success/unit/FunctionNestedBindingXXFreeA.dhall view
@@ -1,1 +1,4 @@+{-+    This test has free variables, so it doesn't typecheck+-} \(x: Bool) -> \(x: Bool) -> [x, x@0, x@1, x@2, x@3]
dhall-lang/tests/alpha-normalization/success/unit/FunctionNestedBindingXYB.dhall view
@@ -1,1 +1,1 @@-\(_: Bool) -> \(_: Bool) -> _@1 && _+λ(_ : Bool) → λ(_ : Bool) → _@1 && _
dhall-lang/tests/alpha-normalization/success/unit/FunctionTypeBindingUnderscoreA.dhall view
@@ -1,1 +1,1 @@-A → B+Bool → Natural
dhall-lang/tests/alpha-normalization/success/unit/FunctionTypeBindingUnderscoreB.dhall view
@@ -1,1 +1,1 @@-A → B+Bool → Natural
dhall-lang/tests/alpha-normalization/success/unit/FunctionTypeBindingXA.dhall view
@@ -1,1 +1,1 @@-∀(x : A) → x+∀(x : Type) → x
dhall-lang/tests/alpha-normalization/success/unit/FunctionTypeBindingXB.dhall view
@@ -1,1 +1,1 @@-A → _+Type → _
dhall-lang/tests/alpha-normalization/success/unit/FunctionTypeNestedBindingXA.dhall view
@@ -1,1 +1,1 @@-∀(x : A) → B → x+∀(x : Type) → Type → x
dhall-lang/tests/alpha-normalization/success/unit/FunctionTypeNestedBindingXB.dhall view
@@ -1,1 +1,1 @@-A → B → _@1+Type → Type → _@1
+ dhall-lang/tests/binary-decode/failure/unit/ApplyNoArgs.dhallb view

binary file changed (absent → 6 bytes)

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

binary file changed (absent → 6 bytes)

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

binary file changed (absent → 4 bytes)

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

binary file changed (absent → 4 bytes)

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

binary file changed (absent → 6 bytes)

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

binary file changed (absent → 6 bytes)

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

binary file changed (absent → 6 bytes)

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

binary file changed (absent → 4 bytes)

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

binary file changed (absent → 16 bytes)

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

binary file changed (absent → 18 bytes)

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

binary file changed (absent → 3 bytes)

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

binary file changed (absent → 11 bytes)

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

binary file changed (absent → 114 bytes)

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

binary file changed (absent → 11 bytes)

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

binary file changed (absent → 9 bytes)

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

binary file changed (absent → 3 bytes)

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

binary file changed (absent → 3 bytes)

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

binary file changed (absent → 3 bytes)

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

binary file changed (absent → 5 bytes)

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

binary file changed (absent → 13 bytes)

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

binary file changed (absent → 3 bytes)

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

binary file changed (absent → 9 bytes)

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

binary file changed (absent → 11 bytes)

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

binary file changed (absent → 26 bytes)

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

binary file changed (absent → 20 bytes)

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

binary file changed (absent → 13 bytes)

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

binary file changed (absent → 7 bytes)

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

binary file changed (absent → 4 bytes)

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

binary file changed (absent → 5 bytes)

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

binary file changed (absent → 4 bytes)

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

binary file changed (absent → 13 bytes)

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

binary file changed (absent → 3 bytes)

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

binary file changed (absent → 5 bytes)

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

binary file changed (absent → 5 bytes)

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

binary file changed (absent → 5 bytes)

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

binary file changed (absent → 5 bytes)

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

binary file changed (absent → 5 bytes)

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

binary file changed (absent → 5 bytes)

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

binary file changed (absent → 5 bytes)

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

binary file changed (absent → 5 bytes)

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

binary file changed (absent → 5 bytes)

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

binary file changed (absent → 5 bytes)

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

binary file changed (absent → 5 bytes)

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

binary file changed (absent → 5 bytes)

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

binary file changed (absent → 5 bytes)

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

binary file changed (absent → 13 bytes)

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

binary file changed (absent → 5 bytes)

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

binary file changed (absent → 12 bytes)

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

binary file changed (absent → 4 bytes)

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

binary file changed (absent → 11 bytes)

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

binary file changed (absent → 9 bytes)

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

binary file changed (absent → 6 bytes)

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

binary file changed (absent → 7 bytes)

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

binary file changed (absent → 11 bytes)

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

binary file changed (absent → 12 bytes)

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

binary file changed (absent → 9 bytes)

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

binary file changed (absent → 10 bytes)

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

binary file changed (absent → 41 bytes)

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

binary file changed (absent → 36 bytes)

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

binary file changed (absent → 36 bytes)

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

binary file changed (absent → 41 bytes)

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

binary file changed (absent → 46 bytes)

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

binary file changed (absent → 32 bytes)

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

binary file changed (absent → 36 bytes)

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

binary file changed (absent → 29 bytes)

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

binary file changed (absent → 29 bytes)

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

binary file changed (absent → 29 bytes)

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

binary file changed (absent → 29 bytes)

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

binary file changed (absent → 6 bytes)

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

binary file changed (absent → 42 bytes)

+ dhall-lang/tests/import/cache/dhall/1220618f785ce8f3930a9144398f576f0a992544b51212bc9108c31b4e670dc6ed21 view
@@ -0,0 +1,1 @@+‚xevil string from bad cache
+ dhall-lang/tests/import/data/cors/AllowedAll.dhall view
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/AllowedAll.dhall
+ dhall-lang/tests/import/data/cors/Empty.dhall view
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/Empty.dhall
+ dhall-lang/tests/import/data/cors/NoCORS.dhall view
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/NoCORS.dhall
+ dhall-lang/tests/import/data/cors/Null.dhall view
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/Null.dhall
+ dhall-lang/tests/import/data/cors/OnlyGithub.dhall view
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/OnlyGithub.dhall
+ dhall-lang/tests/import/data/cors/OnlyOther.dhall view
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/OnlyOther.dhall
+ dhall-lang/tests/import/data/cors/OnlySelf.dhall view
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/OnlySelf.dhall
+ dhall-lang/tests/import/data/cors/Prelude.dhall view
@@ -0,0 +1,1 @@+https://prelude.dhall-lang.org/List/length
+ dhall-lang/tests/import/data/cors/SelfImportAbsolute.dhall view
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/SelfImportAbsolute.dhall
+ dhall-lang/tests/import/data/cors/SelfImportRelative.dhall view
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/SelfImportRelative.dhall
dhall-lang/tests/import/data/cycle.dhall view
@@ -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/doesNotTypecheck.dhall view
@@ -0,0 +1,1 @@+0 0
+ dhall-lang/tests/import/data/example.bin view
@@ -0,0 +1,1 @@+#Eg‰«Íï
− dhall-lang/tests/import/data/fieldOrder/1.dhall
@@ -1,1 +0,0 @@-{ foo = 1, bar = True }
− dhall-lang/tests/import/data/fieldOrder/2.dhall
@@ -1,1 +0,0 @@-{ bar = True, foo = 1 }
+ dhall-lang/tests/import/data/file with spaces.txt view
@@ -0,0 +1,1 @@+True
+ dhall-lang/tests/import/data/importBoundary.dhall view
@@ -0,0 +1,3 @@+-- This file contains a free variable. This should be a type error, even if the variable+-- is in scope in the importing expression+x
+ dhall-lang/tests/import/data/nested.dhall view
@@ -0,0 +1,1 @@+{ x = ./simple.dhall sha256:15f52ecf91c94c1baac02d5a4964b2ed8fa401641a2c8a95e8306ec7c1e3b8d2 }
+ dhall-lang/tests/import/data/poisonedCache.dhall view
@@ -0,0 +1,4 @@+{- This file has a poisoned cache entry.  We want to+   ensure we ignore cache entries which don't match+   the hash -}+"Correct benign content"
dhall-lang/tests/import/data/referentiallyOpaque.dhall view
@@ -9,12 +9,10 @@    this file attempts to import a referentially opaque import (an environment    variable in this case) to verify that the import fails. -   For this test file we need to select a referentially opaque import that would-   likely succeed if imported on its own, so that a non-compliant implementation-   doesn't fail this test for the wrong reason (i.e. due to the referentially-   opaque not being present).  In general, we can't guarantee that referentially-   opaque imports exist (because they are referentially opaque!), but the-   `HOME` environment variable has a high likelihood of bring present on a POSIX-   system.+   For this test file we need to select a referentially opaque import that+   would succeed if imported on its own, so that a non-compliant implementation+   doesn't fail this test for the wrong reason (i.e. due to the import not+   being present).  We thus use the `DHALL_TEST_VAR` environment variable, that+   is expected to be set when running import tests. -}-env:HOME as Text+env:DHALL_TEST_VAR as Text
+ dhall-lang/tests/import/data/simpleLocation.dhall view
@@ -0,0 +1,1 @@+./simple.dhall as Location
+ dhall-lang/tests/import/data/userAgent.dhall view
@@ -0,0 +1,1 @@+"Dhall (from import)"
+ dhall-lang/tests/import/failure/customHeadersUsingBoundVariable.dhall view
@@ -0,0 +1,15 @@+{- This is a type error because the custom headers are type-checked with an+   empty context.  This is necessary because:++   * import resolution precedes β-normalization+   * we also don't want custom headers to leak program state anyway++   This should fail due to the `x` within the custom header being an unbound+   variable+-}++let x = "Bar"++in https://httpbin.org/headers+     using [ { mapKey = "Foo", mapValue = x } ]+     as Text
− dhall-lang/tests/import/failure/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/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/EnvUnset.dhall view
@@ -0,0 +1,1 @@+env:DHALL_TEST_UNSET
+ dhall-lang/tests/import/failure/unit/EnvUnsetAsText.dhall view
@@ -0,0 +1,1 @@+env:DHALL_TEST_UNSET as Text
+ dhall-lang/tests/import/failure/unit/FileMissing.dhall view
@@ -0,0 +1,1 @@+./not-a-file.dhall
+ dhall-lang/tests/import/failure/unit/HashMismatch.dhall view
@@ -0,0 +1,1 @@+../data/simple.dhall sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ dhall-lang/tests/import/failure/unit/HashMismatch2.dhall view
@@ -0,0 +1,2 @@+-- This ensures that even if the file gets imported without hash first, the hash check is not skipped later+../../data/simple.dhall + ../../data/simple.dhall sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + ../../data/simple.dhall
+ dhall-lang/tests/import/failure/unit/Missing.dhall view
@@ -0,0 +1,1 @@+missing
+ dhall-lang/tests/import/failure/unit/VarAcrossImportBoundary.dhall view
@@ -0,0 +1,1 @@+\(x: Bool) -> ../../data/importBoundary.dhall
+ dhall-lang/tests/import/failure/unit/cors/Empty.dhall view
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/Empty.dhall
+ dhall-lang/tests/import/failure/unit/cors/NoCORS.dhall view
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/NoCORS.dhall
+ dhall-lang/tests/import/failure/unit/cors/Null.dhall view
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/Null.dhall
+ dhall-lang/tests/import/failure/unit/cors/OnlyOther.dhall view
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/OnlyOther.dhall
+ dhall-lang/tests/import/failure/unit/cors/OnlySelf.dhall view
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/OnlySelf.dhall
+ dhall-lang/tests/import/failure/unit/cors/TwoHops.dhall view
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/TwoHopsFail.dhall
+ dhall-lang/tests/import/home/hello.dhall view
@@ -0,0 +1,1 @@+"hello"
− dhall-lang/tests/import/success/alternativeEnvNaturalA.dhall
@@ -1,1 +0,0 @@-env:UNSET1 as Text ? env:UNSET2 ? missing ? env:UNSET3 ? 2
− dhall-lang/tests/import/success/alternativeEnvNaturalB.dhall
@@ -1,1 +0,0 @@-2
− dhall-lang/tests/import/success/alternativeEnvSimpleA.dhall
@@ -1,1 +0,0 @@-env:UNSET ? 3
− dhall-lang/tests/import/success/alternativeEnvSimpleB.dhall
@@ -1,1 +0,0 @@-3
− dhall-lang/tests/import/success/alternativeHashMismatchA.dhall
@@ -1,2 +0,0 @@-  ../data/simple.dhall sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-? 42
− dhall-lang/tests/import/success/alternativeHashMismatchB.dhall
@@ -1,1 +0,0 @@-42
− dhall-lang/tests/import/success/alternativeNaturalA.dhall
@@ -1,1 +0,0 @@-4 ? missing
− dhall-lang/tests/import/success/alternativeNaturalB.dhall
@@ -1,1 +0,0 @@-4
− dhall-lang/tests/import/success/alternativeParseErrorA.dhall
@@ -1,1 +0,0 @@-(../data/example.txt) ? 42
− dhall-lang/tests/import/success/alternativeParseErrorB.dhall
@@ -1,1 +0,0 @@-42
− dhall-lang/tests/import/success/asTextA.dhall
@@ -1,1 +0,0 @@-../data/example.txt as Text
− dhall-lang/tests/import/success/asTextB.dhall
@@ -1,3 +0,0 @@-''-Hello, world!-''
dhall-lang/tests/import/success/customHeadersA.dhall view
@@ -1,3 +1,3 @@ https://httpbin.org/user-agent-  using [ { header = "User-Agent", value = "Dhall" } ]+  using [ { mapKey = "User-Agent", mapValue = "Dhall" } ]   as Text
− dhall-lang/tests/import/success/fieldOrderA.dhall
@@ -1,5 +0,0 @@-{ example0 =-    ../data/fieldOrder/1.dhall sha256:d8ae15ff5a40ee7973a23ba75cd98f8e39d14aeb6e1e3f18aadb092fcb825194-, example1 =-    ../data/fieldOrder/2.dhall sha256:d8ae15ff5a40ee7973a23ba75cd98f8e39d14aeb6e1e3f18aadb092fcb825194-}
− dhall-lang/tests/import/success/fieldOrderB.dhall
@@ -1,1 +0,0 @@-{ example0 = { bar = True, foo = 1 }, example1 = { bar = True, foo = 1 } }
+ dhall-lang/tests/import/success/hashFromCacheA.dhall view
@@ -0,0 +1,11 @@+{-+An import with an integrity check MUST be fetched from the cache if possible.++If you have set XDG_CACHE_HOME as described in tests/README.md, this hash will+be available in the cache, so even though this is a `missing` import, it can be+resolved by its hash.++(If you're interested, the value is a fully-αβ-normalized copy of+Prelude/Optional/null)+-}+missing sha256:3871180b87ecaba8b53fffb2a8b52d3fce98098fab09a6f759358b9e8042eedc
+ dhall-lang/tests/import/success/hashFromCacheB.dhall view
@@ -0,0 +1,3 @@+λ(_ : Type) →+λ(_ : Optional _) →+  merge { None = True, Some = λ(_ : _@1) → False } _
dhall-lang/tests/import/success/headerForwardingA.dhall view
@@ -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 [ { header = "Test", value = "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/nestedHashA.dhall view
@@ -0,0 +1,1 @@+../data/nested.dhall sha256:add9792d79d9e03918e3236f32c6f8e89dbc05efac3451eb835676275f2c20a5
+ dhall-lang/tests/import/success/nestedHashB.dhall view
@@ -0,0 +1,1 @@+{ x = 3 }
dhall-lang/tests/import/success/noHeaderForwardingA.dhall view
@@ -3,4 +3,4 @@    https://httpbin.org/user-agent -} https://raw.githubusercontent.com/dhall-lang/dhall-lang/master/tests/import/success/customHeadersA.dhall-  using [ { header = "User-Agent", value = "Secret" } ]+  using [ { mapKey = "User-Agent", mapValue = "Secret" } ]
+ dhall-lang/tests/import/success/originHeadersA.dhall view
@@ -0,0 +1,1 @@+https://httpbin.org/user-agent as Text
+ dhall-lang/tests/import/success/originHeadersB.dhall view
@@ -0,0 +1,5 @@+''+{+  "user-agent": "Dhall"+}+''
+ dhall-lang/tests/import/success/originHeadersENV.dhall view
@@ -0,0 +1,10 @@+toMap+  { DHALL_HEADERS =+      ''+      toMap {+        `httpbin.org:443` = toMap {+          `User-Agent` = "Dhall"+        }+      }+      ''+  }
+ dhall-lang/tests/import/success/originHeadersImportA.dhall view
@@ -0,0 +1,1 @@+https://httpbin.org/user-agent as Text
+ dhall-lang/tests/import/success/originHeadersImportB.dhall view
@@ -0,0 +1,5 @@+''+{+  "user-agent": "Dhall (from import)"+}+''
+ dhall-lang/tests/import/success/originHeadersImportENV.dhall view
@@ -0,0 +1,10 @@+toMap+  { DHALL_HEADERS =+      ''+      toMap {+        `httpbin.org:443` = toMap {+          `User-Agent` = ./dhall-lang/tests/import/data/userAgent.dhall+        }+      }+      ''+  }
+ dhall-lang/tests/import/success/originHeadersImportFromEnvA.dhall view
@@ -0,0 +1,1 @@+https://httpbin.org/user-agent as Text
+ dhall-lang/tests/import/success/originHeadersImportFromEnvB.dhall view
@@ -0,0 +1,5 @@+''+{+  "user-agent": "Dhall (from env)"+}+''
+ dhall-lang/tests/import/success/originHeadersImportFromEnvENV.dhall view
@@ -0,0 +1,11 @@+toMap+  { DHALL_HEADERS =+      ''+      toMap {+        `httpbin.org:443` = toMap {+          `User-Agent` = env:USER_AGENT as Text+        }+      }+      ''+      , USER_AGENT = "Dhall (from env)"+  }
+ dhall-lang/tests/import/success/originHeadersOverrideA.dhall view
@@ -0,0 +1,3 @@+https://httpbin.org/user-agent+  using [ { mapKey = "User-Agent", mapValue = "inline-header" } ]+  as Text
+ dhall-lang/tests/import/success/originHeadersOverrideB.dhall view
@@ -0,0 +1,5 @@+''+{+  "user-agent": "user-header"+}+''
+ dhall-lang/tests/import/success/originHeadersOverrideENV.dhall view
@@ -0,0 +1,10 @@+toMap+  { DHALL_HEADERS =+      ''+      toMap {+        `httpbin.org:443` = toMap {+          `User-Agent` = "user-header"+        }+      }+      ''+  }
+ dhall-lang/tests/import/success/unit/AlternativeChain1A.dhall view
@@ -0,0 +1,1 @@+missing ? missing ? 42
+ dhall-lang/tests/import/success/unit/AlternativeChain1B.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/import/success/unit/AlternativeChain2A.dhall view
@@ -0,0 +1,1 @@+missing ? 42 ? 10
+ dhall-lang/tests/import/success/unit/AlternativeChain2B.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/import/success/unit/AlternativeEnvA.dhall view
@@ -0,0 +1,1 @@+env:DHALL_TEST_UNSET ? 42
+ dhall-lang/tests/import/success/unit/AlternativeEnvB.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/import/success/unit/AlternativeImportErrorA.dhall view
@@ -0,0 +1,1 @@+missing ? 42
+ dhall-lang/tests/import/success/unit/AlternativeImportErrorB.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/import/success/unit/AlternativeNestedImportErrorA.dhall view
@@ -0,0 +1,1 @@+../../failure/missing.dhall ? 42
+ dhall-lang/tests/import/success/unit/AlternativeNestedImportErrorB.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/import/success/unit/AlternativeNoError1A.dhall view
@@ -0,0 +1,1 @@+42 ? 10
+ dhall-lang/tests/import/success/unit/AlternativeNoError1B.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/import/success/unit/AlternativeNoError2A.dhall view
@@ -0,0 +1,1 @@+42 ? missing
+ dhall-lang/tests/import/success/unit/AlternativeNoError2B.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/import/success/unit/AlternativeNoError3A.dhall view
@@ -0,0 +1,1 @@+env:DHALL_TEST_VAR ? 10
+ dhall-lang/tests/import/success/unit/AlternativeNoError3B.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/import/success/unit/AlternativeSubExprA.dhall view
@@ -0,0 +1,1 @@+missing + 10 ? 42
+ dhall-lang/tests/import/success/unit/AlternativeSubExprB.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/import/success/unit/AlternativeWithVariableA.dhall view
@@ -0,0 +1,1 @@+let x = 0 in (missing ? x)
+ dhall-lang/tests/import/success/unit/AlternativeWithVariableB.dhall view
@@ -0,0 +1,1 @@+let x = 0 in x
+ dhall-lang/tests/import/success/unit/AlternativeWithWrongVariable1A.dhall view
@@ -0,0 +1,1 @@+\(x: Natural) -> x ? y
+ dhall-lang/tests/import/success/unit/AlternativeWithWrongVariable1B.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → x
+ dhall-lang/tests/import/success/unit/AlternativeWithWrongVariable2A.dhall view
@@ -0,0 +1,1 @@+\(x: Natural) -> (y + missing) ? x
+ dhall-lang/tests/import/success/unit/AlternativeWithWrongVariable2B.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → x
+ dhall-lang/tests/import/success/unit/AsBytesA.dhall view
@@ -0,0 +1,1 @@+../../data/example.bin as Bytes
+ dhall-lang/tests/import/success/unit/AsBytesB.dhall view
@@ -0,0 +1,1 @@+0x"0123456789abcdef"
+ dhall-lang/tests/import/success/unit/AsTextA.dhall view
@@ -0,0 +1,1 @@+../../data/example.txt as Text
+ dhall-lang/tests/import/success/unit/AsTextB.dhall view
@@ -0,0 +1,3 @@+''+Hello, world!+''
+ dhall-lang/tests/import/success/unit/DontCacheIfHashA.dhall view
@@ -0,0 +1,5 @@+-- The let triggers a loading of `simple.dhall` in the cache,+-- but the second import uses a hash that corresponds to a different file already in the content-addressed store.+-- This test ensures that we retrieve the value corresponding to the hash and not the path even if the path is in cache.+let x = ../../data/simple.dhall+in ../../data/simple.dhall sha256:3871180b87ecaba8b53fffb2a8b52d3fce98098fab09a6f759358b9e8042eedc
+ dhall-lang/tests/import/success/unit/DontCacheIfHashB.dhall view
@@ -0,0 +1,1 @@+let x = 3 in λ(_ : Type) → λ(_ : Optional _) → merge { `None` = True, `Some` = λ(_ : _@1) → False } _
+ dhall-lang/tests/import/success/unit/EnvSetA.dhall view
@@ -0,0 +1,1 @@+env:DHALL_TEST_VAR
+ dhall-lang/tests/import/success/unit/EnvSetAsTextA.dhall view
@@ -0,0 +1,1 @@+env:DHALL_TEST_VAR as Text
+ dhall-lang/tests/import/success/unit/EnvSetAsTextB.dhall view
@@ -0,0 +1,1 @@+"6 * 7"
+ dhall-lang/tests/import/success/unit/EnvSetB.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/import/success/unit/FilenameWithSpacesA.dhall view
@@ -0,0 +1,1 @@+../../data/"file with spaces.txt"
+ dhall-lang/tests/import/success/unit/FilenameWithSpacesB.dhall view
@@ -0,0 +1,1 @@+True
+ dhall-lang/tests/import/success/unit/IgnorePoisonedCacheA.dhall view
@@ -0,0 +1,1 @@+../../data/poisonedCache.dhall sha256:618f785ce8f3930a9144398f576f0a992544b51212bc9108c31b4e670dc6ed21
+ dhall-lang/tests/import/success/unit/IgnorePoisonedCacheB.dhall view
@@ -0,0 +1,1 @@+"Correct benign content"
+ dhall-lang/tests/import/success/unit/ImportRelativeToHomeA.dhall view
@@ -0,0 +1,1 @@+~/hello.dhall ++ " world"
+ dhall-lang/tests/import/success/unit/ImportRelativeToHomeB.dhall view
@@ -0,0 +1,1 @@+"hello" ++ " world"
+ dhall-lang/tests/import/success/unit/MixImportModesA.dhall view
@@ -0,0 +1,2 @@+-- This is to ensure caching doesn't accidentally confuse import modes+{ n = ../../data/simple.dhall, txt = ../../data/simple.dhall as Text, loc = ../../data/simple.dhall as Location }
+ dhall-lang/tests/import/success/unit/MixImportModesB.dhall view
@@ -0,0 +1,1 @@+{ loc = < Environment: Text | Local: Text | Missing | Remote: Text >.Local "./dhall-lang/tests/import/data/simple.dhall", n = 3, txt = "3\n" }
+ dhall-lang/tests/import/success/unit/NormalizeA.dhall view
@@ -0,0 +1,1 @@+../../../../../dhall-lang/tests/normalization/success/unit/OperatorPlusOneAndOneA.dhall
+ dhall-lang/tests/import/success/unit/NormalizeB.dhall view
@@ -0,0 +1,1 @@+2
+ dhall-lang/tests/import/success/unit/QuotedPathA.dhall view
@@ -0,0 +1,1 @@+../".."/"data"/"example.txt" as Text
+ dhall-lang/tests/import/success/unit/QuotedPathB.dhall view
@@ -0,0 +1,3 @@+''+Hello, world!+''
+ dhall-lang/tests/import/success/unit/RecoverTransitiveFailureA.dhall view
@@ -0,0 +1,1 @@+../../failure/unit/FileMissing.dhall ? 0
+ dhall-lang/tests/import/success/unit/RecoverTransitiveFailureB.dhall view
@@ -0,0 +1,1 @@+0
+ dhall-lang/tests/import/success/unit/RemoteAsTextA.dhall view
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-lang/0b983b92aa2222dc3e292c20550ee37dea3f41df/tests/import/data/example.txt as Text
+ dhall-lang/tests/import/success/unit/RemoteAsTextB.dhall view
@@ -0,0 +1,3 @@+''+Hello, world!+''
+ dhall-lang/tests/import/success/unit/SimpleA.dhall view
@@ -0,0 +1,1 @@+../../data/simple.dhall
+ dhall-lang/tests/import/success/unit/SimpleB.dhall view
@@ -0,0 +1,1 @@+3
+ dhall-lang/tests/import/success/unit/SimpleHashA.dhall view
@@ -0,0 +1,1 @@+../../data/simple.dhall sha256:15f52ecf91c94c1baac02d5a4964b2ed8fa401641a2c8a95e8306ec7c1e3b8d2
+ dhall-lang/tests/import/success/unit/SimpleHashB.dhall view
@@ -0,0 +1,1 @@+3
+ dhall-lang/tests/import/success/unit/SimpleRemoteA.dhall view
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-lang/0b983b92aa2222dc3e292c20550ee37dea3f41df/tests/import/data/simple.dhall
+ dhall-lang/tests/import/success/unit/SimpleRemoteB.dhall view
@@ -0,0 +1,1 @@+3
+ dhall-lang/tests/import/success/unit/asLocation/AbsoluteA.dhall view
@@ -0,0 +1,1 @@+/absolute/import as Location
+ dhall-lang/tests/import/success/unit/asLocation/AbsoluteB.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Local+  "/absolute/import"
+ dhall-lang/tests/import/success/unit/asLocation/Canonicalize1A.dhall view
@@ -0,0 +1,1 @@+./foo/./bar/import.dhall as Location
+ dhall-lang/tests/import/success/unit/asLocation/Canonicalize1B.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Local+  "./dhall-lang/tests/import/success/unit/asLocation/foo/bar/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/Canonicalize2A.dhall view
@@ -0,0 +1,1 @@+./foo/baz/../bar/import.dhall as Location
+ dhall-lang/tests/import/success/unit/asLocation/Canonicalize2B.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Local+  "./dhall-lang/tests/import/success/unit/asLocation/foo/bar/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/Canonicalize3A.dhall view
@@ -0,0 +1,1 @@+./../bar/import.dhall as Location
+ dhall-lang/tests/import/success/unit/asLocation/Canonicalize3B.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Local+  "./dhall-lang/tests/import/success/unit/bar/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/Canonicalize4A.dhall view
@@ -0,0 +1,1 @@+../../bar/import.dhall as Location
+ dhall-lang/tests/import/success/unit/asLocation/Canonicalize4B.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Local+  "./dhall-lang/tests/import/success/bar/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/Canonicalize5A.dhall view
@@ -0,0 +1,1 @@+./foo/../../bar/import.dhall as Location
+ dhall-lang/tests/import/success/unit/asLocation/Canonicalize5B.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Local+  "./dhall-lang/tests/import/success/unit/bar/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/Chain1A.dhall view
@@ -0,0 +1,1 @@+./Relative1A.dhall
+ dhall-lang/tests/import/success/unit/asLocation/Chain1B.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Local+  "./dhall-lang/tests/import/success/unit/asLocation/some/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/Chain2A.dhall view
@@ -0,0 +1,1 @@+./Canonicalize4A.dhall
+ dhall-lang/tests/import/success/unit/asLocation/Chain2B.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Local+  "./dhall-lang/tests/import/success/bar/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/Chain3A.dhall view
@@ -0,0 +1,1 @@+../asLocation/Canonicalize4A.dhall
+ dhall-lang/tests/import/success/unit/asLocation/Chain3B.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Local+  "./dhall-lang/tests/import/success/bar/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/DontTryResolvingA.dhall view
@@ -0,0 +1,1 @@+(missing as Location) ? 42  -- `missing` fails as an import, but definitely resolves as Location
+ dhall-lang/tests/import/success/unit/asLocation/DontTryResolvingB.dhall view
@@ -0,0 +1,1 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Missing
+ dhall-lang/tests/import/success/unit/asLocation/EnvA.dhall view
@@ -0,0 +1,1 @@+env:DHALL_TEST_VAR as Location
+ dhall-lang/tests/import/success/unit/asLocation/EnvB.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Environment+  "DHALL_TEST_VAR"
+ dhall-lang/tests/import/success/unit/asLocation/HashA.dhall view
@@ -0,0 +1,6 @@+{-+  If you have set XDG_CACHE_HOME as described in tests/README.md, this hash will+  be available in the cache. Since this is an `as Location` test however, you+  mustn't use the cache value here.+-}+./some/import.dhall sha256:efc43103e49b56c5bf089db8e0365bbfc455b8a2f0dc6ee5727a3586f85969fd as Location
+ dhall-lang/tests/import/success/unit/asLocation/HashB.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Local+  "./dhall-lang/tests/import/success/unit/asLocation/some/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/HomeA.dhall view
@@ -0,0 +1,1 @@+~/some/import.dhall as Location
+ dhall-lang/tests/import/success/unit/asLocation/HomeB.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Local+  "~/some/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/MissingA.dhall view
@@ -0,0 +1,1 @@+missing as Location
+ dhall-lang/tests/import/success/unit/asLocation/MissingB.dhall view
@@ -0,0 +1,1 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Missing
+ dhall-lang/tests/import/success/unit/asLocation/Relative1A.dhall view
@@ -0,0 +1,1 @@+./some/import.dhall as Location
+ dhall-lang/tests/import/success/unit/asLocation/Relative1B.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Local+  "./dhall-lang/tests/import/success/unit/asLocation/some/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/Relative2A.dhall view
@@ -0,0 +1,1 @@+../some/import.dhall as Location
+ dhall-lang/tests/import/success/unit/asLocation/Relative2B.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Local+  "./dhall-lang/tests/import/success/unit/some/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/RemoteA.dhall view
@@ -0,0 +1,1 @@+https://example.com/foo/import.dhall as Location
+ dhall-lang/tests/import/success/unit/asLocation/RemoteB.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Remote+  "https://example.com/foo/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/RemoteCanonicalize1A.dhall view
@@ -0,0 +1,1 @@+https://example.com/foo/./bar/import.dhall as Location
+ dhall-lang/tests/import/success/unit/asLocation/RemoteCanonicalize1B.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Remote+  "https://example.com/foo/bar/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/RemoteCanonicalize2A.dhall view
@@ -0,0 +1,1 @@+https://example.com/foo/bar/../baz/import.dhall as Location
+ dhall-lang/tests/import/success/unit/asLocation/RemoteCanonicalize2B.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Remote+  "https://example.com/foo/baz/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/RemoteCanonicalize3A.dhall view
@@ -0,0 +1,1 @@+https://example.com/foo/bar/../../baz/import.dhall as Location
+ dhall-lang/tests/import/success/unit/asLocation/RemoteCanonicalize3B.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Remote+  "https://example.com/baz/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/RemoteCanonicalize4A.dhall view
@@ -0,0 +1,4 @@+{-+  The standardized behaviour does not respect https://tools.ietf.org/html/rfc3986#section-5.2 .+-}+https://example.com/../bar/import.dhall as Location
+ dhall-lang/tests/import/success/unit/asLocation/RemoteCanonicalize4B.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Remote+  "https://example.com/../bar/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/RemoteChain1A.dhall view
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-lang/0b983b92aa2222dc3e292c20550ee37dea3f41df/tests/import/data/simpleLocation.dhall
+ dhall-lang/tests/import/success/unit/asLocation/RemoteChain1B.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Remote+  "https://raw.githubusercontent.com/dhall-lang/dhall-lang/0b983b92aa2222dc3e292c20550ee37dea3f41df/tests/import/data/simple.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/RemoteChain2A.dhall view
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/Nadrieril/dhall-rust/f7d8c64a9799f139ad65427c2518376adb9e2e2f/dhall/tests/import/success/unit/asLocation/Canonicalize3A.dhall
+ dhall-lang/tests/import/success/unit/asLocation/RemoteChain2B.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Remote+  "https://raw.githubusercontent.com/Nadrieril/dhall-rust/f7d8c64a9799f139ad65427c2518376adb9e2e2f/dhall/tests/import/success/unit/bar/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/RemoteChain3A.dhall view
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/Nadrieril/dhall-rust/f7d8c64a9799f139ad65427c2518376adb9e2e2f/dhall/tests/import/success/unit/asLocation/Canonicalize5A.dhall
+ dhall-lang/tests/import/success/unit/asLocation/RemoteChain3B.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Remote+  "https://raw.githubusercontent.com/Nadrieril/dhall-rust/f7d8c64a9799f139ad65427c2518376adb9e2e2f/dhall/tests/import/success/unit/bar/import.dhall"
+ dhall-lang/tests/import/success/unit/asLocation/RemoteChainEnvA.dhall view
@@ -0,0 +1,5 @@+{-+    This test verifies that `env:VAR as Location` isn't rejected as referentially opaque,+    as `env:VAR` on its own would.+-}+https://raw.githubusercontent.com/Nadrieril/dhall-rust/f7d8c64a9799f139ad65427c2518376adb9e2e2f/dhall/tests/import/success/unit/asLocation/EnvA.dhall
+ dhall-lang/tests/import/success/unit/asLocation/RemoteChainEnvB.dhall view
@@ -0,0 +1,2 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Environment+  "HOME"
+ dhall-lang/tests/import/success/unit/asLocation/RemoteChainMissingA.dhall view
@@ -0,0 +1,6 @@+{- This test verifies that `missing as Location` succeeds when chained since:+   * The `missing` is never actually resolved (due to the `as Location`)+   * The `missing` should be treated as referentially transparent (and therefore+     be a valid transitive dependency of a remote import)+-}+https://raw.githubusercontent.com/Nadrieril/dhall-rust/f7d8c64a9799f139ad65427c2518376adb9e2e2f/dhall/tests/import/success/unit/asLocation/MissingA.dhall
+ dhall-lang/tests/import/success/unit/asLocation/RemoteChainMissingB.dhall view
@@ -0,0 +1,1 @@+< Environment : Text | Local : Text | Missing | Remote : Text >.Missing
+ dhall-lang/tests/import/success/unit/cors/AllowedAllA.dhall view
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/AllowedAll.dhall
+ dhall-lang/tests/import/success/unit/cors/AllowedAllB.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/import/success/unit/cors/NoCORSFromLocalA.dhall view
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/NoCORS.dhall
+ dhall-lang/tests/import/success/unit/cors/NoCORSFromLocalB.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/import/success/unit/cors/OnlyGithubA.dhall view
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/OnlyGithub.dhall
+ dhall-lang/tests/import/success/unit/cors/OnlyGithubB.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/import/success/unit/cors/PreludeA.dhall view
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-lang/acee30866a179c9e9bb3fc02ec8be2883685eb14/tests/import/data/cors/Prelude.dhall
+ dhall-lang/tests/import/success/unit/cors/PreludeB.dhall view
@@ -0,0 +1,1 @@+List/length
+ dhall-lang/tests/import/success/unit/cors/SelfImportAbsolute2A.dhall view
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/SelfImportAbsolute.dhall
+ dhall-lang/tests/import/success/unit/cors/SelfImportAbsolute2B.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/import/success/unit/cors/SelfImportAbsoluteA.dhall view
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/SelfImportAbsolute.dhall
+ dhall-lang/tests/import/success/unit/cors/SelfImportAbsoluteB.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/import/success/unit/cors/SelfImportRelative2A.dhall view
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/SelfImportRelative.dhall
+ dhall-lang/tests/import/success/unit/cors/SelfImportRelative2B.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/import/success/unit/cors/SelfImportRelativeA.dhall view
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/SelfImportRelative.dhall
+ dhall-lang/tests/import/success/unit/cors/SelfImportRelativeB.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/import/success/unit/cors/TwoHopsA.dhall view
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/TwoHopsSuccess.dhall
+ dhall-lang/tests/import/success/unit/cors/TwoHopsB.dhall view
@@ -0,0 +1,1 @@+42
+ dhall-lang/tests/normalization/success/WithRecordValueA.dhall view
@@ -0,0 +1,12 @@+{-  This test illustrates that `with a = { c = 2 }` is not the same thing as+    `with a.c = 2`:++    * `with a = { c = 2 }` overrides the entire value of the field `a` with a new+      record containing only `c = 2`++    * `with a.c = 2` extends or updates the record stored underneath `a` to+      set the field `c` to `2`.++    Compare this to the `WithNested` test, which contains the `a.c = 2` case+-}+{ a.b = 1 } with a = { c = 2 }
+ dhall-lang/tests/normalization/success/WithRecordValueB.dhall view
@@ -0,0 +1,1 @@+{ a = { c = 2 } }
− dhall-lang/tests/normalization/success/prelude/Bool/and/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Bool/and [ True, False, True ]
− dhall-lang/tests/normalization/success/prelude/Bool/and/0B.dhall
@@ -1,1 +0,0 @@-False
− dhall-lang/tests/normalization/success/prelude/Bool/and/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Bool/and ([] : List Bool)
− dhall-lang/tests/normalization/success/prelude/Bool/and/1B.dhall
@@ -1,1 +0,0 @@-True
− dhall-lang/tests/normalization/success/prelude/Bool/build/0A.dhall
@@ -1,2 +0,0 @@-../../../../../../Prelude/Bool/build -(λ(bool : Type) → λ(true : bool) → λ(false : bool) → true)
− dhall-lang/tests/normalization/success/prelude/Bool/build/0B.dhall
@@ -1,1 +0,0 @@-True
− dhall-lang/tests/normalization/success/prelude/Bool/build/1A.dhall
@@ -1,2 +0,0 @@-../../../../../../Prelude/Bool/build -(λ(bool : Type) → λ(true : bool) → λ(false : bool) → false)
− dhall-lang/tests/normalization/success/prelude/Bool/build/1B.dhall
@@ -1,1 +0,0 @@-False
− dhall-lang/tests/normalization/success/prelude/Bool/even/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Bool/even [ False, True, False ]
− dhall-lang/tests/normalization/success/prelude/Bool/even/0B.dhall
@@ -1,1 +0,0 @@-True
− dhall-lang/tests/normalization/success/prelude/Bool/even/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Bool/even [ False, True ]
− dhall-lang/tests/normalization/success/prelude/Bool/even/1B.dhall
@@ -1,1 +0,0 @@-False
− dhall-lang/tests/normalization/success/prelude/Bool/even/2A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Bool/even [ False ]
− dhall-lang/tests/normalization/success/prelude/Bool/even/2B.dhall
@@ -1,1 +0,0 @@-False
− dhall-lang/tests/normalization/success/prelude/Bool/even/3A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Bool/even ([] : List Bool)
− dhall-lang/tests/normalization/success/prelude/Bool/even/3B.dhall
@@ -1,1 +0,0 @@-True
− dhall-lang/tests/normalization/success/prelude/Bool/fold/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Bool/fold True Natural 0 1
− dhall-lang/tests/normalization/success/prelude/Bool/fold/0B.dhall
@@ -1,1 +0,0 @@-0
− dhall-lang/tests/normalization/success/prelude/Bool/fold/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Bool/fold False Natural 0 1
− dhall-lang/tests/normalization/success/prelude/Bool/fold/1B.dhall
@@ -1,1 +0,0 @@-1
− dhall-lang/tests/normalization/success/prelude/Bool/not/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Bool/not True
− dhall-lang/tests/normalization/success/prelude/Bool/not/0B.dhall
@@ -1,1 +0,0 @@-False
− dhall-lang/tests/normalization/success/prelude/Bool/not/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Bool/not False
− dhall-lang/tests/normalization/success/prelude/Bool/not/1B.dhall
@@ -1,1 +0,0 @@-True
− dhall-lang/tests/normalization/success/prelude/Bool/odd/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Bool/odd [ True, False, True ]
− dhall-lang/tests/normalization/success/prelude/Bool/odd/0B.dhall
@@ -1,1 +0,0 @@-False
− dhall-lang/tests/normalization/success/prelude/Bool/odd/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Bool/odd [ True, False ]
− dhall-lang/tests/normalization/success/prelude/Bool/odd/1B.dhall
@@ -1,1 +0,0 @@-True
− dhall-lang/tests/normalization/success/prelude/Bool/odd/2A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Bool/odd [ True ]
− dhall-lang/tests/normalization/success/prelude/Bool/odd/2B.dhall
@@ -1,1 +0,0 @@-True
− dhall-lang/tests/normalization/success/prelude/Bool/odd/3A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Bool/odd ([] : List Bool)
− dhall-lang/tests/normalization/success/prelude/Bool/odd/3B.dhall
@@ -1,1 +0,0 @@-False
− dhall-lang/tests/normalization/success/prelude/Bool/or/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Bool/or [ True, False, True ]
− dhall-lang/tests/normalization/success/prelude/Bool/or/0B.dhall
@@ -1,1 +0,0 @@-True
− dhall-lang/tests/normalization/success/prelude/Bool/or/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Bool/or ([] : List Bool)
− dhall-lang/tests/normalization/success/prelude/Bool/or/1B.dhall
@@ -1,1 +0,0 @@-False
− dhall-lang/tests/normalization/success/prelude/Bool/show/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Bool/show True
− dhall-lang/tests/normalization/success/prelude/Bool/show/0B.dhall
@@ -1,1 +0,0 @@-"True"
− dhall-lang/tests/normalization/success/prelude/Bool/show/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Bool/show False
− dhall-lang/tests/normalization/success/prelude/Bool/show/1B.dhall
@@ -1,1 +0,0 @@-"False"
− dhall-lang/tests/normalization/success/prelude/Double/show/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Double/show -3.1
− dhall-lang/tests/normalization/success/prelude/Double/show/0B.dhall
@@ -1,1 +0,0 @@-"-3.1"
− dhall-lang/tests/normalization/success/prelude/Double/show/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Double/show 0.4
− dhall-lang/tests/normalization/success/prelude/Double/show/1B.dhall
@@ -1,1 +0,0 @@-"0.4"
− dhall-lang/tests/normalization/success/prelude/Integer/show/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Integer/show -3
− dhall-lang/tests/normalization/success/prelude/Integer/show/0B.dhall
@@ -1,1 +0,0 @@-"-3"
− dhall-lang/tests/normalization/success/prelude/Integer/show/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Integer/show +0
− dhall-lang/tests/normalization/success/prelude/Integer/show/1B.dhall
@@ -1,1 +0,0 @@-"+0"
− dhall-lang/tests/normalization/success/prelude/Integer/toDouble/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Integer/toDouble -3
− dhall-lang/tests/normalization/success/prelude/Integer/toDouble/0B.dhall
@@ -1,1 +0,0 @@--3.0
− dhall-lang/tests/normalization/success/prelude/Integer/toDouble/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Integer/toDouble +2
− dhall-lang/tests/normalization/success/prelude/Integer/toDouble/1B.dhall
@@ -1,1 +0,0 @@-2.0
− dhall-lang/tests/normalization/success/prelude/List/all/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/all Natural Natural/even [ 2, 3, 5 ]
− dhall-lang/tests/normalization/success/prelude/List/all/0B.dhall
@@ -1,1 +0,0 @@-False
− dhall-lang/tests/normalization/success/prelude/List/all/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/all Natural Natural/even ([] : List Natural)
− dhall-lang/tests/normalization/success/prelude/List/all/1B.dhall
@@ -1,1 +0,0 @@-True
− dhall-lang/tests/normalization/success/prelude/List/any/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/any Natural Natural/even [ 2, 3, 5 ]
− dhall-lang/tests/normalization/success/prelude/List/any/0B.dhall
@@ -1,1 +0,0 @@-True
− dhall-lang/tests/normalization/success/prelude/List/any/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/any Natural Natural/even ([] : List Natural)
− dhall-lang/tests/normalization/success/prelude/List/any/1B.dhall
@@ -1,1 +0,0 @@-False
− dhall-lang/tests/normalization/success/prelude/List/build/0A.dhall
@@ -1,7 +0,0 @@-../../../../../../Prelude/List/build-Text-( λ(list : Type)-→ λ(cons : Text → list → list)-→ λ(nil : list)-→ cons "ABC" (cons "DEF" nil)-)
− dhall-lang/tests/normalization/success/prelude/List/build/0B.dhall
@@ -1,1 +0,0 @@-[ "ABC", "DEF" ]
− dhall-lang/tests/normalization/success/prelude/List/build/1A.dhall
@@ -1,7 +0,0 @@-../../../../../../Prelude/List/build-Text-( λ(list : Type)-→ λ(cons : Text → list → list)-→ λ(nil : list)-→ nil-)
− dhall-lang/tests/normalization/success/prelude/List/build/1B.dhall
@@ -1,1 +0,0 @@-[] : List Text
− dhall-lang/tests/normalization/success/prelude/List/concat/0A.dhall
@@ -1,5 +0,0 @@-../../../../../../Prelude/List/concat Natural-[ [ 0, 1, 2 ]-, [ 3, 4 ]-, [ 5, 6, 7, 8 ]-]
− dhall-lang/tests/normalization/success/prelude/List/concat/0B.dhall
@@ -1,1 +0,0 @@-[ 0, 1, 2, 3, 4, 5, 6, 7, 8 ]
− dhall-lang/tests/normalization/success/prelude/List/concat/1A.dhall
@@ -1,5 +0,0 @@-../../../../../../Prelude/List/concat Natural-[ [] : List Natural-, [] : List Natural-, [] : List Natural-]
− dhall-lang/tests/normalization/success/prelude/List/concat/1B.dhall
@@ -1,1 +0,0 @@-[] : List Natural
− dhall-lang/tests/normalization/success/prelude/List/concatMap/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/concatMap Natural Natural (λ(n : Natural) → [ n, n ]) [ 2, 3, 5 ]
− dhall-lang/tests/normalization/success/prelude/List/concatMap/0B.dhall
@@ -1,1 +0,0 @@-[ 2, 2, 3, 3, 5, 5 ]
− dhall-lang/tests/normalization/success/prelude/List/concatMap/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/concatMap Natural Natural (λ(n : Natural) → [ n, n ]) ([] : List Natural)
− dhall-lang/tests/normalization/success/prelude/List/concatMap/1B.dhall
@@ -1,1 +0,0 @@-[] : List Natural
− dhall-lang/tests/normalization/success/prelude/List/filter/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/filter Natural Natural/even [ 2, 3, 5 ]
− dhall-lang/tests/normalization/success/prelude/List/filter/0B.dhall
@@ -1,1 +0,0 @@-[ 2 ]
− dhall-lang/tests/normalization/success/prelude/List/filter/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/filter Natural Natural/odd [ 2, 3, 5 ]
− dhall-lang/tests/normalization/success/prelude/List/filter/1B.dhall
@@ -1,1 +0,0 @@-[ 3, 5 ]
− dhall-lang/tests/normalization/success/prelude/List/fold/0A.dhall
@@ -1,6 +0,0 @@-../../../../../../Prelude/List/fold-Natural-[ 2, 3, 5 ]-Natural-(λ(x : Natural) → λ(y : Natural) → x + y)-0
− dhall-lang/tests/normalization/success/prelude/List/fold/0B.dhall
@@ -1,1 +0,0 @@-10
− dhall-lang/tests/normalization/success/prelude/List/fold/1A.dhall
@@ -1,7 +0,0 @@-  λ(nil : Natural)-→ ../../../../../../Prelude/List/fold-  Natural-  [ 2, 3, 5 ]-  Natural-  (λ(x : Natural) → λ(y : Natural) → x + y)-  nil
− dhall-lang/tests/normalization/success/prelude/List/fold/1B.dhall
@@ -1,1 +0,0 @@-λ(nil : Natural) → 2 + (3 + (5 + nil))
− dhall-lang/tests/normalization/success/prelude/List/fold/2A.dhall
@@ -1,4 +0,0 @@-  λ(list : Type)-→ λ(cons : Natural → list → list)-→ λ(nil : list)-→ ../../../../../../Prelude/List/fold Natural [ 2, 3, 5 ] list cons nil
− dhall-lang/tests/normalization/success/prelude/List/fold/2B.dhall
@@ -1,4 +0,0 @@-  λ(list : Type)-→ λ(cons : Natural → list → list)-→ λ(nil : list)-→ cons 2 (cons 3 (cons 5 nil))
− dhall-lang/tests/normalization/success/prelude/List/generate/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/generate 5 Bool Natural/even
− dhall-lang/tests/normalization/success/prelude/List/generate/0B.dhall
@@ -1,1 +0,0 @@-[ True, False, True, False, True ]
− dhall-lang/tests/normalization/success/prelude/List/generate/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/generate 0 Bool Natural/even
− dhall-lang/tests/normalization/success/prelude/List/generate/1B.dhall
@@ -1,1 +0,0 @@-[] : List Bool
− dhall-lang/tests/normalization/success/prelude/List/head/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/head Natural [ 0, 1, 2 ]
− dhall-lang/tests/normalization/success/prelude/List/head/0B.dhall
@@ -1,1 +0,0 @@-Some 0
− dhall-lang/tests/normalization/success/prelude/List/head/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/head Natural ([] : List Natural)
− dhall-lang/tests/normalization/success/prelude/List/head/1B.dhall
@@ -1,1 +0,0 @@-None Natural
− dhall-lang/tests/normalization/success/prelude/List/indexed/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/indexed Bool [ True, False, True ]
− dhall-lang/tests/normalization/success/prelude/List/indexed/0B.dhall
@@ -1,4 +0,0 @@-[ { index = 0, value = True }-, { index = 1, value = False }-, { index = 2, value = True }-]
− dhall-lang/tests/normalization/success/prelude/List/indexed/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/indexed Bool ([] : List Bool)
− dhall-lang/tests/normalization/success/prelude/List/indexed/1B.dhall
@@ -1,1 +0,0 @@-[] : List { index : Natural, value : Bool }
− dhall-lang/tests/normalization/success/prelude/List/iterate/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/iterate 10 Natural (λ(x : Natural) → x * 2) 1
− dhall-lang/tests/normalization/success/prelude/List/iterate/0B.dhall
@@ -1,1 +0,0 @@-[ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512 ]
− dhall-lang/tests/normalization/success/prelude/List/iterate/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/iterate 0 Natural (λ(x : Natural) → x * 2) 1
− dhall-lang/tests/normalization/success/prelude/List/iterate/1B.dhall
@@ -1,1 +0,0 @@-[] : List Natural
− dhall-lang/tests/normalization/success/prelude/List/last/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/last Natural [ 0, 1, 2 ]
− dhall-lang/tests/normalization/success/prelude/List/last/0B.dhall
@@ -1,1 +0,0 @@-Some 2
− dhall-lang/tests/normalization/success/prelude/List/last/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/last Natural ([] : List Natural)
− dhall-lang/tests/normalization/success/prelude/List/last/1B.dhall
@@ -1,1 +0,0 @@-None Natural
− dhall-lang/tests/normalization/success/prelude/List/length/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/length Natural [ 0, 1, 2 ]
− dhall-lang/tests/normalization/success/prelude/List/length/0B.dhall
@@ -1,1 +0,0 @@-3
− dhall-lang/tests/normalization/success/prelude/List/length/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/length Natural ([] : List Natural)
− dhall-lang/tests/normalization/success/prelude/List/length/1B.dhall
@@ -1,1 +0,0 @@-0
− dhall-lang/tests/normalization/success/prelude/List/map/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/map Natural Bool Natural/even [ 2, 3, 5 ]
− dhall-lang/tests/normalization/success/prelude/List/map/0B.dhall
@@ -1,1 +0,0 @@-[ True, False, False ]
− dhall-lang/tests/normalization/success/prelude/List/map/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/map Natural Bool Natural/even ([] : List Natural)
− dhall-lang/tests/normalization/success/prelude/List/map/1B.dhall
@@ -1,1 +0,0 @@-[] : List Bool
− dhall-lang/tests/normalization/success/prelude/List/null/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/null Natural [ 0, 1, 2 ]
− dhall-lang/tests/normalization/success/prelude/List/null/0B.dhall
@@ -1,1 +0,0 @@-False
− dhall-lang/tests/normalization/success/prelude/List/null/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/null Natural ([] : List Natural)
− dhall-lang/tests/normalization/success/prelude/List/null/1B.dhall
@@ -1,1 +0,0 @@-True
− dhall-lang/tests/normalization/success/prelude/List/replicate/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/replicate 9 Natural 1
− dhall-lang/tests/normalization/success/prelude/List/replicate/0B.dhall
@@ -1,1 +0,0 @@-[ 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
− dhall-lang/tests/normalization/success/prelude/List/replicate/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/replicate 0 Natural 1
− dhall-lang/tests/normalization/success/prelude/List/replicate/1B.dhall
@@ -1,1 +0,0 @@-[] : List Natural
− dhall-lang/tests/normalization/success/prelude/List/reverse/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/reverse Natural [ 0, 1, 2 ]
− dhall-lang/tests/normalization/success/prelude/List/reverse/0B.dhall
@@ -1,1 +0,0 @@-[ 2, 1, 0 ]
− dhall-lang/tests/normalization/success/prelude/List/reverse/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/reverse Natural ([] : List Natural)
− dhall-lang/tests/normalization/success/prelude/List/reverse/1B.dhall
@@ -1,1 +0,0 @@-[] : List Natural
− dhall-lang/tests/normalization/success/prelude/List/shifted/0A.dhall
@@ -1,15 +0,0 @@-../../../../../../Prelude/List/shifted-Bool-[ [ { index = 0, value = True }-  , { index = 1, value = True }-  , { index = 2, value = False }-  ]-, [ { index = 0, value = False }-  , { index = 1, value = False }-  ]-, [ { index = 0, value = True }-  , { index = 1, value = True }-  , { index = 2, value = True }-  , { index = 3, value = True }-  ]-]
− dhall-lang/tests/normalization/success/prelude/List/shifted/0B.dhall
@@ -1,10 +0,0 @@-[ { index = 0, value = True }-, { index = 1, value = True }-, { index = 2, value = False }-, { index = 3, value = False }-, { index = 4, value = False }-, { index = 5, value = True }-, { index = 6, value = True }-, { index = 7, value = True }-, { index = 8, value = True }-]
− dhall-lang/tests/normalization/success/prelude/List/shifted/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/shifted Bool ([] : List (List { index : Natural, value : Bool }))
− dhall-lang/tests/normalization/success/prelude/List/shifted/1B.dhall
@@ -1,1 +0,0 @@-[] : List { index : Natural, value : Bool }
− dhall-lang/tests/normalization/success/prelude/List/unzip/0A.dhall
@@ -1,7 +0,0 @@-../../../../../../Prelude/List/unzip-Text-Bool-[ { _1 = "ABC", _2 = True }-, { _1 = "DEF", _2 = False }-, { _1 = "GHI", _2 = True }-]
− dhall-lang/tests/normalization/success/prelude/List/unzip/0B.dhall
@@ -1,1 +0,0 @@-{ _1 = [ "ABC", "DEF", "GHI" ], _2 = [ True, False, True ] }
− dhall-lang/tests/normalization/success/prelude/List/unzip/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/unzip Text Bool ([] : List { _1 : Text, _2 : Bool })
− dhall-lang/tests/normalization/success/prelude/List/unzip/1B.dhall
@@ -1,1 +0,0 @@-{ _1 = [] : List Text, _2 = [] : List Bool }
− dhall-lang/tests/normalization/success/prelude/Natural/build/0A.dhall
@@ -1,6 +0,0 @@-../../../../../../Prelude/Natural/build-( λ(natural : Type)-→ λ(succ : natural → natural)-→ λ(zero : natural)-→ succ (succ (succ zero))-)
− dhall-lang/tests/normalization/success/prelude/Natural/build/0B.dhall
@@ -1,1 +0,0 @@-3
− dhall-lang/tests/normalization/success/prelude/Natural/build/1A.dhall
@@ -1,6 +0,0 @@-../../../../../../Prelude/Natural/build-( λ(natural : Type)-→ λ(succ : natural → natural)-→ λ(zero : natural)-→ zero-)
− dhall-lang/tests/normalization/success/prelude/Natural/build/1B.dhall
@@ -1,1 +0,0 @@-0
− dhall-lang/tests/normalization/success/prelude/Natural/enumerate/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/enumerate 10
− dhall-lang/tests/normalization/success/prelude/Natural/enumerate/0B.dhall
@@ -1,1 +0,0 @@-[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
− dhall-lang/tests/normalization/success/prelude/Natural/enumerate/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/enumerate 0
− dhall-lang/tests/normalization/success/prelude/Natural/enumerate/1B.dhall
@@ -1,1 +0,0 @@-[] : List Natural
− dhall-lang/tests/normalization/success/prelude/Natural/even/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/even 3
− dhall-lang/tests/normalization/success/prelude/Natural/even/0B.dhall
@@ -1,1 +0,0 @@-False
− dhall-lang/tests/normalization/success/prelude/Natural/even/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/even 0
− dhall-lang/tests/normalization/success/prelude/Natural/even/1B.dhall
@@ -1,1 +0,0 @@-True
− dhall-lang/tests/normalization/success/prelude/Natural/fold/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/fold 3 Natural (λ(x : Natural) → 5 * x) 1
− dhall-lang/tests/normalization/success/prelude/Natural/fold/0B.dhall
@@ -1,1 +0,0 @@-125
− dhall-lang/tests/normalization/success/prelude/Natural/fold/1A.dhall
@@ -1,1 +0,0 @@-λ(zero : Natural) → ../../../../../../Prelude/Natural/fold 3 Natural (λ(x : Natural) → 5 * x) zero
− dhall-lang/tests/normalization/success/prelude/Natural/fold/1B.dhall
@@ -1,1 +0,0 @@-λ(zero : Natural) → 5 * (5 * (5 * zero))
− dhall-lang/tests/normalization/success/prelude/Natural/fold/2A.dhall
@@ -1,4 +0,0 @@-  λ(natural : Type)-→ λ(succ : natural → natural)-→ λ(zero : natural)-→ ../../../../../../Prelude/Natural/fold 3 natural succ zero
− dhall-lang/tests/normalization/success/prelude/Natural/fold/2B.dhall
@@ -1,4 +0,0 @@-  λ(natural : Type)-→ λ(succ : natural → natural)-→ λ(zero : natural)-→ succ (succ (succ zero))
− dhall-lang/tests/normalization/success/prelude/Natural/isZero/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/isZero 2
− dhall-lang/tests/normalization/success/prelude/Natural/isZero/0B.dhall
@@ -1,1 +0,0 @@-False
− dhall-lang/tests/normalization/success/prelude/Natural/isZero/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/isZero 0
− dhall-lang/tests/normalization/success/prelude/Natural/isZero/1B.dhall
@@ -1,1 +0,0 @@-True
− dhall-lang/tests/normalization/success/prelude/Natural/odd/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/odd 3
− dhall-lang/tests/normalization/success/prelude/Natural/odd/0B.dhall
@@ -1,1 +0,0 @@-True
− dhall-lang/tests/normalization/success/prelude/Natural/odd/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/odd 0
− dhall-lang/tests/normalization/success/prelude/Natural/odd/1B.dhall
@@ -1,1 +0,0 @@-False
− dhall-lang/tests/normalization/success/prelude/Natural/product/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/product [ 2, 3, 5 ]
− dhall-lang/tests/normalization/success/prelude/Natural/product/0B.dhall
@@ -1,1 +0,0 @@-30
− dhall-lang/tests/normalization/success/prelude/Natural/product/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/product ([] : List Natural)
− dhall-lang/tests/normalization/success/prelude/Natural/product/1B.dhall
@@ -1,1 +0,0 @@-1
− dhall-lang/tests/normalization/success/prelude/Natural/show/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/show 3
− dhall-lang/tests/normalization/success/prelude/Natural/show/0B.dhall
@@ -1,1 +0,0 @@-"3"
− dhall-lang/tests/normalization/success/prelude/Natural/show/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/show 0
− dhall-lang/tests/normalization/success/prelude/Natural/show/1B.dhall
@@ -1,1 +0,0 @@-"0"
− dhall-lang/tests/normalization/success/prelude/Natural/sum/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/sum [ 2, 3, 5 ]
− dhall-lang/tests/normalization/success/prelude/Natural/sum/0B.dhall
@@ -1,1 +0,0 @@-10
− dhall-lang/tests/normalization/success/prelude/Natural/sum/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/sum ([] : List Natural)
− dhall-lang/tests/normalization/success/prelude/Natural/sum/1B.dhall
@@ -1,1 +0,0 @@-0
− dhall-lang/tests/normalization/success/prelude/Natural/toDouble/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/toDouble 3
− dhall-lang/tests/normalization/success/prelude/Natural/toDouble/0B.dhall
@@ -1,1 +0,0 @@-3.0
− dhall-lang/tests/normalization/success/prelude/Natural/toDouble/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/toDouble 0
− dhall-lang/tests/normalization/success/prelude/Natural/toDouble/1B.dhall
@@ -1,1 +0,0 @@-0.0
− dhall-lang/tests/normalization/success/prelude/Natural/toInteger/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/toInteger 3
− dhall-lang/tests/normalization/success/prelude/Natural/toInteger/0B.dhall
@@ -1,1 +0,0 @@-+3
− dhall-lang/tests/normalization/success/prelude/Natural/toInteger/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/toInteger 0
− dhall-lang/tests/normalization/success/prelude/Natural/toInteger/1B.dhall
@@ -1,1 +0,0 @@-+0
− dhall-lang/tests/normalization/success/prelude/Optional/all/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/all Natural Natural/even (Some 3)
− dhall-lang/tests/normalization/success/prelude/Optional/all/0B.dhall
@@ -1,1 +0,0 @@-False
− dhall-lang/tests/normalization/success/prelude/Optional/all/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/all Natural Natural/even (None Natural)
− dhall-lang/tests/normalization/success/prelude/Optional/all/1B.dhall
@@ -1,1 +0,0 @@-True
− dhall-lang/tests/normalization/success/prelude/Optional/any/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/any Natural Natural/even (Some 2)
− dhall-lang/tests/normalization/success/prelude/Optional/any/0B.dhall
@@ -1,1 +0,0 @@-True
− dhall-lang/tests/normalization/success/prelude/Optional/any/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/any Natural Natural/even (None Natural)
− dhall-lang/tests/normalization/success/prelude/Optional/any/1B.dhall
@@ -1,1 +0,0 @@-False
− dhall-lang/tests/normalization/success/prelude/Optional/build/0A.dhall
@@ -1,7 +0,0 @@-../../../../../../Prelude/Optional/build-Natural-( λ(optional : Type)-→ λ(some : Natural → optional)-→ λ(none : optional)-→ some 1-)
− dhall-lang/tests/normalization/success/prelude/Optional/build/0B.dhall
@@ -1,1 +0,0 @@-Some 1
− dhall-lang/tests/normalization/success/prelude/Optional/build/1A.dhall
@@ -1,7 +0,0 @@-../../../../../../Prelude/Optional/build-Natural-( λ(optional : Type)-→ λ(some : Natural → optional)-→ λ(none : optional)-→ none-)
− dhall-lang/tests/normalization/success/prelude/Optional/build/1B.dhall
@@ -1,1 +0,0 @@-None Natural
− dhall-lang/tests/normalization/success/prelude/Optional/concat/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/concat Natural (Some (Some 1))
− dhall-lang/tests/normalization/success/prelude/Optional/concat/0B.dhall
@@ -1,1 +0,0 @@-Some 1
− dhall-lang/tests/normalization/success/prelude/Optional/concat/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/concat Natural (Some (None Natural))
− dhall-lang/tests/normalization/success/prelude/Optional/concat/1B.dhall
@@ -1,1 +0,0 @@-None Natural
− dhall-lang/tests/normalization/success/prelude/Optional/concat/2A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/concat Natural (None (Optional Natural))
− dhall-lang/tests/normalization/success/prelude/Optional/concat/2B.dhall
@@ -1,1 +0,0 @@-None Natural
− dhall-lang/tests/normalization/success/prelude/Optional/filter/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/filter Natural Natural/even (Some 2)
− dhall-lang/tests/normalization/success/prelude/Optional/filter/0B.dhall
@@ -1,1 +0,0 @@-Some 2
− dhall-lang/tests/normalization/success/prelude/Optional/filter/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/filter Natural Natural/odd (Some 2)
− dhall-lang/tests/normalization/success/prelude/Optional/filter/1B.dhall
@@ -1,1 +0,0 @@-None Natural
− dhall-lang/tests/normalization/success/prelude/Optional/fold/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/fold Natural (Some 2) Natural (λ(x : Natural) → x) 0
− dhall-lang/tests/normalization/success/prelude/Optional/fold/0B.dhall
@@ -1,1 +0,0 @@-2
− dhall-lang/tests/normalization/success/prelude/Optional/fold/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/fold Natural (None Natural) Natural (λ(x : Natural) → x) 0
− dhall-lang/tests/normalization/success/prelude/Optional/fold/1B.dhall
@@ -1,1 +0,0 @@-0
− dhall-lang/tests/normalization/success/prelude/Optional/head/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/head Natural [ None Natural, Some 1, Some 2 ]
− dhall-lang/tests/normalization/success/prelude/Optional/head/0B.dhall
@@ -1,1 +0,0 @@-Some 1
− dhall-lang/tests/normalization/success/prelude/Optional/head/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/head Natural [ None Natural, None Natural ]
− dhall-lang/tests/normalization/success/prelude/Optional/head/1B.dhall
@@ -1,1 +0,0 @@-None Natural
− dhall-lang/tests/normalization/success/prelude/Optional/head/2A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/head Natural ([] : List (Optional Natural))
− dhall-lang/tests/normalization/success/prelude/Optional/head/2B.dhall
@@ -1,1 +0,0 @@-None Natural
− dhall-lang/tests/normalization/success/prelude/Optional/last/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/last Natural [ None Natural, Some 1, Some 2 ]
− dhall-lang/tests/normalization/success/prelude/Optional/last/0B.dhall
@@ -1,1 +0,0 @@-Some 2
− dhall-lang/tests/normalization/success/prelude/Optional/last/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/last Natural [ None Natural, None Natural ]
− dhall-lang/tests/normalization/success/prelude/Optional/last/1B.dhall
@@ -1,1 +0,0 @@-None Natural
− dhall-lang/tests/normalization/success/prelude/Optional/last/2A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/last Natural ([] : List (Optional Natural))
− dhall-lang/tests/normalization/success/prelude/Optional/last/2B.dhall
@@ -1,1 +0,0 @@-None Natural
− dhall-lang/tests/normalization/success/prelude/Optional/length/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/length Natural (Some 2)
− dhall-lang/tests/normalization/success/prelude/Optional/length/0B.dhall
@@ -1,1 +0,0 @@-1
− dhall-lang/tests/normalization/success/prelude/Optional/length/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/length Natural (None Natural)
− dhall-lang/tests/normalization/success/prelude/Optional/length/1B.dhall
@@ -1,1 +0,0 @@-0
− dhall-lang/tests/normalization/success/prelude/Optional/map/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/map Natural Bool Natural/even (Some 3)
− dhall-lang/tests/normalization/success/prelude/Optional/map/0B.dhall
@@ -1,1 +0,0 @@-Some False
− dhall-lang/tests/normalization/success/prelude/Optional/map/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/map Natural Bool Natural/even (None Natural)
− dhall-lang/tests/normalization/success/prelude/Optional/map/1B.dhall
@@ -1,1 +0,0 @@-None Bool
− dhall-lang/tests/normalization/success/prelude/Optional/null/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/null Natural (Some 2)
− dhall-lang/tests/normalization/success/prelude/Optional/null/0B.dhall
@@ -1,1 +0,0 @@-False
− dhall-lang/tests/normalization/success/prelude/Optional/null/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/null Natural (None Natural)
− dhall-lang/tests/normalization/success/prelude/Optional/null/1B.dhall
@@ -1,1 +0,0 @@-True
− dhall-lang/tests/normalization/success/prelude/Optional/toList/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/toList Natural (Some 1)
− dhall-lang/tests/normalization/success/prelude/Optional/toList/0B.dhall
@@ -1,1 +0,0 @@-[ 1 ]
− dhall-lang/tests/normalization/success/prelude/Optional/toList/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/toList Natural (None Natural)
− dhall-lang/tests/normalization/success/prelude/Optional/toList/1B.dhall
@@ -1,1 +0,0 @@-[] : List Natural
− dhall-lang/tests/normalization/success/prelude/Optional/unzip/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/unzip Text Bool (Some { _1 = "ABC", _2 = True })
− dhall-lang/tests/normalization/success/prelude/Optional/unzip/0B.dhall
@@ -1,1 +0,0 @@-{ _1 = Some "ABC", _2 = Some True }
− dhall-lang/tests/normalization/success/prelude/Optional/unzip/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/unzip Text Bool (None { _1 : Text, _2 : Bool })
− dhall-lang/tests/normalization/success/prelude/Optional/unzip/1B.dhall
@@ -1,1 +0,0 @@-{ _1 = None Text, _2 = None Bool }
− dhall-lang/tests/normalization/success/prelude/Text/concat/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Text/concat [ "ABC", "DEF", "GHI" ]
− dhall-lang/tests/normalization/success/prelude/Text/concat/0B.dhall
@@ -1,1 +0,0 @@-"ABCDEFGHI"
− dhall-lang/tests/normalization/success/prelude/Text/concat/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Text/concat ([] : List Text)
− dhall-lang/tests/normalization/success/prelude/Text/concat/1B.dhall
@@ -1,1 +0,0 @@-""
− dhall-lang/tests/normalization/success/prelude/Text/concatMap/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Text/concatMap Natural (λ(n : Natural) → "${Natural/show n} ") [ 0, 1, 2 ]
− dhall-lang/tests/normalization/success/prelude/Text/concatMap/0B.dhall
@@ -1,1 +0,0 @@-"0 1 2 "
− dhall-lang/tests/normalization/success/prelude/Text/concatMap/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Text/concatMap Natural (λ(n : Natural) → "${Natural/show n} ") ([] : List Natural)
− dhall-lang/tests/normalization/success/prelude/Text/concatMap/1B.dhall
@@ -1,1 +0,0 @@-""
− dhall-lang/tests/normalization/success/prelude/Text/concatMapSep/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Text/concatMapSep ", " Natural Natural/show [ 0, 1, 2 ]
− dhall-lang/tests/normalization/success/prelude/Text/concatMapSep/0B.dhall
@@ -1,1 +0,0 @@-"0, 1, 2"
− dhall-lang/tests/normalization/success/prelude/Text/concatMapSep/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Text/concatMapSep ", " Natural Natural/show ([] : List Natural)
− dhall-lang/tests/normalization/success/prelude/Text/concatMapSep/1B.dhall
@@ -1,1 +0,0 @@-""
− dhall-lang/tests/normalization/success/prelude/Text/concatSep/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Text/concatSep ", " [ "ABC", "DEF", "GHI" ]
− dhall-lang/tests/normalization/success/prelude/Text/concatSep/0B.dhall
@@ -1,1 +0,0 @@-"ABC, DEF, GHI"
− dhall-lang/tests/normalization/success/prelude/Text/concatSep/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Text/concatSep ", " ([] : List Text)
− dhall-lang/tests/normalization/success/prelude/Text/concatSep/1B.dhall
@@ -1,1 +0,0 @@-""
− dhall-lang/tests/normalization/success/prelude/Text/show/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Text/show "ABC"
− dhall-lang/tests/normalization/success/prelude/Text/show/0B.dhall
@@ -1,1 +0,0 @@-"\"ABC\""
− dhall-lang/tests/normalization/success/prelude/Text/show/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Text/show "\u0000 \$ \\ \n \u263a"
− dhall-lang/tests/normalization/success/prelude/Text/show/1B.dhall
@@ -1,1 +0,0 @@-"\"\\u0000 \\u0024 \\\\ \\n ☺\""
+ dhall-lang/tests/normalization/success/regression/ComplexRecordSimplificationA.dhall view
@@ -0,0 +1,1 @@+\(foo: { x: Bool, y: Bool }) -> \(bar: { x: Bool }) -> (foo.{x, y} // bar).{ x }
+ dhall-lang/tests/normalization/success/regression/ComplexRecordSimplificationB.dhall view
@@ -0,0 +1,3 @@+λ(foo : { x : Bool, y : Bool }) →+λ(bar : { x : Bool }) →+  (foo.{ x, y } ⫽ bar).{ x }
+ dhall-lang/tests/normalization/success/regression/NaturalFoldExtraArgA.dhall view
@@ -0,0 +1,2 @@+{- Checks that builtins don't accidentally discard further arguments than their arity -}+Natural/fold 0 (Bool -> Bool) (λ(_ : (Bool -> Bool)) → λ(_ : Bool) → True) (λ(_ : Bool) → False) True
+ dhall-lang/tests/normalization/success/regression/NaturalFoldExtraArgB.dhall view
@@ -0,0 +1,1 @@+False
+ dhall-lang/tests/normalization/success/regression/ToMapQuotedFieldsA.dhall view
@@ -0,0 +1,1 @@+toMap { `if` = 0, `foo%bar` = 1 }
+ dhall-lang/tests/normalization/success/regression/ToMapQuotedFieldsB.dhall view
@@ -0,0 +1,1 @@+[ { mapKey = "foo%bar", mapValue = 1 }, { mapKey = "if", mapValue = 0 } ]
+ dhall-lang/tests/normalization/success/regression/TrickyBinderIdentityA.dhall view
@@ -0,0 +1,1 @@+let T = Natural let ap = λ(f : T → List T) -> λ(x : T) -> f x in ap (λ(x : T) -> ap (λ(y : T) -> [x, y]) 1) 0
+ dhall-lang/tests/normalization/success/regression/TrickyBinderIdentityB.dhall view
@@ -0,0 +1,1 @@+[ 0, 1 ]
+ dhall-lang/tests/normalization/success/regression/UnsaturatedBuiltinsA.dhall view
@@ -0,0 +1,16 @@+{-  The Haskell implementation was incorrectly normalizing partially+    saturated `Natural/fold` and `List/fold` built-ins even though the standard+    requires built-ins to be fully saturated before normalization.++    For example, the Haskell implementation was normalizing `Natural/fold 0` to:++          λ(natural : Type)+        → λ(succ : natural → natural)+        → λ(zero : natural)+        → zero++    ... when the correct result should have been `Natural/fold 0` (no change)+-}+{ example0 = Natural/fold 0+, example1 = List/fold Bool [ True ]+}
+ dhall-lang/tests/normalization/success/regression/UnsaturatedBuiltinsB.dhall view
@@ -0,0 +1,3 @@+{ example0 = Natural/fold 0+, example1 = List/fold Bool [ True ]+}
dhall-lang/tests/normalization/success/remoteSystemsA.dhall view
@@ -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/completionA.dhall view
@@ -0,0 +1,10 @@+let Example =+      { Type = { name : Text, id : Optional Natural }+      , default = { name = "", id = None Natural }+      }++in  { example0 = Example::{=}+    , example1 = Example::{ name = "John Doe" }+    , example2 = Example::{ id = Some 0 }+    , example3 = Example::{ name = "Mary Jane", id = Some 0 }+    }
+ dhall-lang/tests/normalization/success/simple/completionB.dhall view
@@ -0,0 +1,5 @@+{ example0 = { id = None Natural, name = "" }+, example1 = { id = None Natural, name = "John Doe" }+, example2 = { id = Some 0, name = "" }+, example3 = { id = Some 0, name = "Mary Jane" }+}
+ dhall-lang/tests/normalization/success/simple/equalNoCommuteA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x == False
+ dhall-lang/tests/normalization/success/simple/equalNoCommuteB.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x == False
+ dhall-lang/tests/normalization/success/simple/notEqualNoCommuteA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x != True
+ dhall-lang/tests/normalization/success/simple/notEqualNoCommuteB.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x != True
− dhall-lang/tests/normalization/success/simple/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/simple/plusNoCommuteA.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → x + 1
+ dhall-lang/tests/normalization/success/simple/plusNoCommuteB.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → x + 1
+ dhall-lang/tests/normalization/success/simple/timesNoCommuteA.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → x * 2
+ dhall-lang/tests/normalization/success/simple/timesNoCommuteB.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → x * 2
+ dhall-lang/tests/normalization/success/simplifications/issue661A.dhall view
@@ -0,0 +1,17 @@+let T1 = { a : Natural }+let T2 = { a : Natural, b : Text }+let T3 = { z : List { a : Natural, b : Text } }+let T4 = { z : List { b : Text, c : List Natural } }++let Prelude/List/map = ../../../../Prelude/List/map++let f = λ(old : T1) → old ⫽ { b = "Hello" }+let g = λ(old : T2) → { z = [ old, old.{ a } ⫽ { b = "Bye" } ] : List T2 }+let h_ = λ(old : T2) → old.{ b } ⫽ { c = [ old.a ] : List Natural }+let h =+        λ(old : T3)+      → { z = Prelude/List/map T2 { b : Text, c : List Natural } h_ old.z }++let k = λ(old : T1) → h (g (f old))++in k
+ dhall-lang/tests/normalization/success/simplifications/issue661B.dhall view
@@ -0,0 +1,2 @@+  λ(old : { a : Natural })+→ { z = [ { b = "Hello", c = [ old.a ] }, { b = "Bye", c = [ old.a ] } ] }
+ dhall-lang/tests/normalization/success/simplifications/rightBiasedMergeWithinRecordProjectionWithinFieldSelection0A.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool, b : Bool }) → (x ⫽ { c = 0 }).{ a, c }.c
+ dhall-lang/tests/normalization/success/simplifications/rightBiasedMergeWithinRecordProjectionWithinFieldSelection0B.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool, b : Bool }) → 0
+ dhall-lang/tests/normalization/success/simplifications/rightBiasedMergeWithinRecordProjectionWithinFieldSelection1A.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool, b : Bool }) → (x ⫽ { c = 0 }).({ a : Bool, c : Natural }).a
+ dhall-lang/tests/normalization/success/simplifications/rightBiasedMergeWithinRecordProjectionWithinFieldSelection1B.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool, b : Bool }) → x.a
+ dhall-lang/tests/normalization/success/simplifications/rightBiasedMergeWithinRecursiveRecordMergeWithinFieldselectionA.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : {} }) → (x ⫽ { b = 0 } ∧ { a = { c = 1 } }).b
+ dhall-lang/tests/normalization/success/simplifications/rightBiasedMergeWithinRecursiveRecordMergeWithinFieldselectionB.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : {} }) → 0
+ dhall-lang/tests/normalization/success/unit/AssertNormalizeArgumentA.dhall view
@@ -0,0 +1,1 @@+assert : (1 + 1) === (1 + 1)
+ dhall-lang/tests/normalization/success/unit/AssertNormalizeArgumentB.dhall view
@@ -0,0 +1,1 @@+assert : 2 ≡ 2
dhall-lang/tests/normalization/success/unit/BareInterpolationA.dhall view
@@ -1,1 +1,1 @@-"${x}"+λ(x : Text) → "${x}"
dhall-lang/tests/normalization/success/unit/BareInterpolationB.dhall view
@@ -1,1 +1,1 @@-x+λ(x : Text) → x
+ dhall-lang/tests/normalization/success/unit/BytesA.dhall view
@@ -0,0 +1,1 @@+Bytes
+ dhall-lang/tests/normalization/success/unit/BytesB.dhall view
@@ -0,0 +1,1 @@+Bytes
+ dhall-lang/tests/normalization/success/unit/BytesLiteralA.dhall view
@@ -0,0 +1,23 @@+[ 0x"00"+, 0x"01"+, 0x"02"+, 0x"03"+, 0x"04"+, 0x"05"+, 0x"06"+, 0x"07"+, 0x"08"+, 0x"09"+, 0x"0a"+, 0x"0b"+, 0x"0c"+, 0x"0d"+, 0x"0e"+, 0x"0f"+, 0x"0A"+, 0x"0B"+, 0x"0C"+, 0x"0D"+, 0x"0E"+, 0x"0F"+]
+ dhall-lang/tests/normalization/success/unit/BytesLiteralB.dhall view
@@ -0,0 +1,23 @@+[ 0x"00"+, 0x"01"+, 0x"02"+, 0x"03"+, 0x"04"+, 0x"05"+, 0x"06"+, 0x"07"+, 0x"08"+, 0x"09"+, 0x"0a"+, 0x"0b"+, 0x"0c"+, 0x"0d"+, 0x"0e"+, 0x"0f"+, 0x"0A"+, 0x"0B"+, 0x"0C"+, 0x"0D"+, 0x"0E"+, 0x"0F"+]
+ dhall-lang/tests/normalization/success/unit/CompletionA.dhall view
@@ -0,0 +1,1 @@+{ default = {=}, Type = {} }::{=}
+ dhall-lang/tests/normalization/success/unit/CompletionB.dhall view
@@ -0,0 +1,1 @@+{=}
+ dhall-lang/tests/normalization/success/unit/EmptyToMapA.dhall view
@@ -0,0 +1,1 @@+toMap {=} : List {mapKey : Text, mapValue : Natural}
+ dhall-lang/tests/normalization/success/unit/EmptyToMapB.dhall view
@@ -0,0 +1,1 @@+[] : List { mapKey : Text, mapValue : Natural }
+ dhall-lang/tests/normalization/success/unit/EquivalenceNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+(1 + 1) === (1 + 2)
+ dhall-lang/tests/normalization/success/unit/EquivalenceNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+2 ≡ 3
dhall-lang/tests/normalization/success/unit/FunctionApplicationCaptureA.dhall view
@@ -1,1 +1,1 @@-(λ(_ : X) → λ(_ : X) → _@1) x y+(λ(_ : Bool) → λ(_ : Bool) → _@1) True False
dhall-lang/tests/normalization/success/unit/FunctionApplicationCaptureB.dhall view
@@ -1,1 +1,1 @@-x+True
dhall-lang/tests/normalization/success/unit/FunctionApplicationNoSubstituteA.dhall view
@@ -1,1 +1,1 @@-(λ(x : X) → y) x+λ(y : Bool) → (λ(x : Bool) → y) True
dhall-lang/tests/normalization/success/unit/FunctionApplicationNoSubstituteB.dhall view
@@ -1,1 +1,1 @@-y+λ(y : Bool) → y
dhall-lang/tests/normalization/success/unit/FunctionApplicationNormalizeArgumentsA.dhall view
@@ -1,1 +1,3 @@-(if True then a else b) (if True then y else z)+  λ(f : Bool → Natural)+→ λ(x : Bool)+→ (if True then f else f) (if True then x else x)
dhall-lang/tests/normalization/success/unit/FunctionApplicationNormalizeArgumentsB.dhall view
@@ -1,1 +1,1 @@-a y+λ(f : Bool → Natural) → λ(x : Bool) → f x
dhall-lang/tests/normalization/success/unit/FunctionApplicationSubstituteA.dhall view
@@ -1,1 +1,1 @@-(λ(x : X) → x) y+(λ(x : Bool) → x) True
dhall-lang/tests/normalization/success/unit/FunctionApplicationSubstituteB.dhall view
@@ -1,1 +1,1 @@-y+True
dhall-lang/tests/normalization/success/unit/FunctionNormalizeArgumentsA.dhall view
@@ -1,1 +1,1 @@-λ(_ : if True then X else Y) → if True then _ else y+let id = λ(X : Type) → X in λ(x : id Bool) → if True then x else x
dhall-lang/tests/normalization/success/unit/FunctionNormalizeArgumentsB.dhall view
@@ -1,1 +1,1 @@-λ(_ : X) → _+λ(x : Bool) → x
dhall-lang/tests/normalization/success/unit/FunctionTypeNormalizeArgumentsA.dhall view
@@ -1,1 +1,1 @@-(if True then X else Y) → if True then A else B+let id = λ(X : Type) → X in id Bool → id Natural
dhall-lang/tests/normalization/success/unit/FunctionTypeNormalizeArgumentsB.dhall view
@@ -1,1 +1,1 @@-X → A+Bool → Natural
dhall-lang/tests/normalization/success/unit/IfAlternativesIdenticalA.dhall view
@@ -1,1 +1,1 @@-if x then y else y+λ(x : Bool) → λ(y : Natural) → if x then y else y
dhall-lang/tests/normalization/success/unit/IfAlternativesIdenticalB.dhall view
@@ -1,1 +1,1 @@-y+λ(x : Bool) → λ(y : Natural) → y
dhall-lang/tests/normalization/success/unit/IfNormalizePredicateAndBranchesA.dhall view
@@ -1,1 +1,4 @@-if if True then x else y then if True then a else b else if True then c else d+  λ(b : Bool)+→ λ(x : Natural)+→ λ(y : Natural)+→ if if True then b else b then if True then x else x else if True then y else y
dhall-lang/tests/normalization/success/unit/IfNormalizePredicateAndBranchesB.dhall view
@@ -1,1 +1,1 @@-if x then a else c+λ(b : Bool) → λ(x : Natural) → λ(y : Natural) → if b then x else y
dhall-lang/tests/normalization/success/unit/IfTrivialA.dhall view
@@ -1,1 +1,1 @@-if x then True else False+λ(x : Bool) → if x then True else False
dhall-lang/tests/normalization/success/unit/IfTrivialB.dhall view
@@ -1,1 +1,1 @@-x+λ(x : Bool) → x
+ dhall-lang/tests/normalization/success/unit/IntegerClampA.dhall view
@@ -0,0 +1,1 @@+Integer/clamp
+ dhall-lang/tests/normalization/success/unit/IntegerClampB.dhall view
@@ -0,0 +1,1 @@+Integer/clamp
+ dhall-lang/tests/normalization/success/unit/IntegerClampNegativeA.dhall view
@@ -0,0 +1,1 @@+Integer/clamp -6
+ dhall-lang/tests/normalization/success/unit/IntegerClampNegativeB.dhall view
@@ -0,0 +1,1 @@+0
+ dhall-lang/tests/normalization/success/unit/IntegerClampPositiveA.dhall view
@@ -0,0 +1,1 @@+Integer/clamp +5
+ dhall-lang/tests/normalization/success/unit/IntegerClampPositiveB.dhall view
@@ -0,0 +1,1 @@+5
+ dhall-lang/tests/normalization/success/unit/IntegerClampZeroA.dhall view
@@ -0,0 +1,1 @@+Integer/clamp +0
+ dhall-lang/tests/normalization/success/unit/IntegerClampZeroB.dhall view
@@ -0,0 +1,1 @@+0
+ dhall-lang/tests/normalization/success/unit/IntegerNegateA.dhall view
@@ -0,0 +1,1 @@+Integer/negate
+ dhall-lang/tests/normalization/success/unit/IntegerNegateB.dhall view
@@ -0,0 +1,1 @@+Integer/negate
+ dhall-lang/tests/normalization/success/unit/IntegerNegateNegativeA.dhall view
@@ -0,0 +1,1 @@+Integer/negate -7
+ dhall-lang/tests/normalization/success/unit/IntegerNegateNegativeB.dhall view
@@ -0,0 +1,1 @@++7
+ dhall-lang/tests/normalization/success/unit/IntegerNegatePositiveA.dhall view
@@ -0,0 +1,1 @@+Integer/negate +3
+ dhall-lang/tests/normalization/success/unit/IntegerNegatePositiveB.dhall view
@@ -0,0 +1,1 @@+-3
+ dhall-lang/tests/normalization/success/unit/IntegerNegateZeroA.dhall view
@@ -0,0 +1,1 @@+Integer/negate +0
+ dhall-lang/tests/normalization/success/unit/IntegerNegateZeroB.dhall view
@@ -0,0 +1,1 @@++0
dhall-lang/tests/normalization/success/unit/LetA.dhall view
@@ -1,1 +1,1 @@-let x = y in x+λ(y : Bool) → let x = y in x
dhall-lang/tests/normalization/success/unit/LetB.dhall view
@@ -1,1 +1,1 @@-y+λ(y : Bool) → y
dhall-lang/tests/normalization/success/unit/LetWithTypeA.dhall view
@@ -1,1 +1,1 @@-let x : A = y in x+λ(y : Bool) → let x : Bool = y in x
dhall-lang/tests/normalization/success/unit/LetWithTypeB.dhall view
@@ -1,1 +1,1 @@-y+λ(y : Bool) → y
dhall-lang/tests/normalization/success/unit/ListBuildFoldFusionA.dhall view
@@ -1,1 +1,1 @@-List/build A (List/fold A x)+λ(T : Type) → λ(x : List T) → List/build T (List/fold T x)
dhall-lang/tests/normalization/success/unit/ListBuildFoldFusionB.dhall view
@@ -1,1 +1,8 @@-x+  λ(T : Type)+→ λ(x : List T)+→ List/fold+    T+    x+    (List T)+    (λ(a : T) → λ(`as` : List T) → [ a ] # `as`)+    ([] : List T)
dhall-lang/tests/normalization/success/unit/ListBuildImplementationA.dhall view
@@ -1,1 +1,3 @@-List/build A0 (λ(list : Type) → λ(cons : A0 → list → list) → λ(nil : list) → x)+  λ(T : Type)+→ λ(f : ∀(list : Type) → (T → list → list) → list → list)+→ List/build T f
dhall-lang/tests/normalization/success/unit/ListBuildImplementationB.dhall view
@@ -1,1 +1,3 @@-x+  λ(T : Type)+→ λ(f : ∀(list : Type) → (T → list → list) → list → list)+→ f (List T) (λ(a : T) → λ(`as` : List T) → [ a ] # `as`) ([] : List T)
dhall-lang/tests/normalization/success/unit/ListFoldEmptyA.dhall view
@@ -1,1 +1,1 @@-List/fold A0 ([] : List A1) B g x+λ(T : Type) → λ(f : T → Bool → Bool) → List/fold T ([] : List T) Bool f True
dhall-lang/tests/normalization/success/unit/ListFoldEmptyB.dhall view
@@ -1,1 +1,1 @@-x+λ(T : Type) → λ(f : T → Bool → Bool) → True
dhall-lang/tests/normalization/success/unit/ListFoldOneA.dhall view
@@ -1,1 +1,1 @@-List/fold A0 [ x ] B (λ(x : A0) → λ(y : B) → x) z+λ(T : Type) → λ(f : T → Bool → Bool) → λ(x : T) → List/fold T [ x ] Bool f True
dhall-lang/tests/normalization/success/unit/ListFoldOneB.dhall view
@@ -1,1 +1,1 @@-x+λ(T : Type) → λ(f : T → Bool → Bool) → λ(x : T) → f x True
dhall-lang/tests/normalization/success/unit/ListHeadEmptyA.dhall view
@@ -1,1 +1,1 @@-List/head T ([] : List T)+λ(T : Type) → List/head T ([] : List T)
dhall-lang/tests/normalization/success/unit/ListHeadEmptyB.dhall view
@@ -1,1 +1,1 @@-None T+λ(T : Type) → None T
dhall-lang/tests/normalization/success/unit/ListIndexedEmptyA.dhall view
@@ -1,1 +1,1 @@-List/indexed T ([] : List T)+λ(T : Type) → List/indexed T ([] : List T)
dhall-lang/tests/normalization/success/unit/ListIndexedEmptyB.dhall view
@@ -1,1 +1,1 @@-[] : List { index : Natural, value : T }+λ(T : Type) → [] : List { index : Natural, value : T }
dhall-lang/tests/normalization/success/unit/ListLastEmptyA.dhall view
@@ -1,1 +1,1 @@-List/last T ([] : List T)+λ(T : Type) → List/last T ([] : List T)
dhall-lang/tests/normalization/success/unit/ListLastEmptyB.dhall view
@@ -1,1 +1,1 @@-None T+λ(T : Type) → None T
dhall-lang/tests/normalization/success/unit/ListLengthEmptyA.dhall view
@@ -1,1 +1,1 @@-List/length T ([] : List T)+λ(T : Type) → List/length T ([] : List T)
dhall-lang/tests/normalization/success/unit/ListLengthEmptyB.dhall view
@@ -1,1 +1,1 @@-0+λ(T : Type) → 0
dhall-lang/tests/normalization/success/unit/ListNormalizeElementsA.dhall view
@@ -1,1 +1,1 @@-[ if True then x else y ]+λ(x : Bool) → [ if True then x else x ]
dhall-lang/tests/normalization/success/unit/ListNormalizeElementsB.dhall view
@@ -1,1 +1,1 @@-[ x ]+λ(x : Bool) → [ x ]
dhall-lang/tests/normalization/success/unit/ListNormalizeTypeAnnotationA.dhall view
@@ -1,1 +1,1 @@-[] : List (if True then x else y)+[] : { x = List Bool }.x
dhall-lang/tests/normalization/success/unit/ListNormalizeTypeAnnotationB.dhall view
@@ -1,1 +1,1 @@-[] : List x+[] : List Bool
dhall-lang/tests/normalization/success/unit/ListReverseEmptyA.dhall view
@@ -1,1 +1,1 @@-List/reverse T ([] : List T)+λ(T : Type) → List/reverse T ([] : List T)
dhall-lang/tests/normalization/success/unit/ListReverseEmptyB.dhall view
@@ -1,1 +1,1 @@-[] : List T+λ(T : Type) → [] : List T
dhall-lang/tests/normalization/success/unit/MergeA.dhall view
@@ -1,1 +1,1 @@-merge { x = λ(_ : A) → _ } (< x : T >.x y)+λ(T : Type) → λ(f : T → Bool) → λ(x : T) → merge { a = f } (< a : T >.a x)
dhall-lang/tests/normalization/success/unit/MergeB.dhall view
@@ -1,1 +1,1 @@-y+λ(T : Type) → λ(f : T → Bool) → λ(x : T) → f x
dhall-lang/tests/normalization/success/unit/MergeEmptyAlternativeA.dhall view
@@ -1,1 +1,1 @@-merge { x = a } < x >.x+λ(x : Bool) → merge { a = x } < a >.a
dhall-lang/tests/normalization/success/unit/MergeEmptyAlternativeB.dhall view
@@ -1,1 +1,1 @@-a+λ(x : Bool) → x
+ dhall-lang/tests/normalization/success/unit/MergeNoneA.dhall view
@@ -0,0 +1,1 @@+merge { None = False, Some = \(b : Bool) -> b } (None Bool)
+ dhall-lang/tests/normalization/success/unit/MergeNoneB.dhall view
@@ -0,0 +1,1 @@+False
dhall-lang/tests/normalization/success/unit/MergeNormalizeArgumentsA.dhall view
@@ -1,1 +1,3 @@-merge (if True then x else y) (if True then z else b)+  λ(x : { a : Bool })+→ λ(y : < a >)+→ merge (if True then x else x) (if True then y else y)
dhall-lang/tests/normalization/success/unit/MergeNormalizeArgumentsB.dhall view
@@ -1,1 +1,1 @@-merge x z+λ(x : { a : Bool }) → λ(y : < a >) → merge x y
+ dhall-lang/tests/normalization/success/unit/MergeSomeA.dhall view
@@ -0,0 +1,1 @@+merge { None = False, Some = \(b : Bool) -> b } (Some True)
+ dhall-lang/tests/normalization/success/unit/MergeSomeB.dhall view
@@ -0,0 +1,1 @@+True
dhall-lang/tests/normalization/success/unit/MergeWithTypeA.dhall view
@@ -1,1 +1,4 @@-merge { x = λ(_ : A) → _ } (< x : T >.x y) : A+  λ(T : Type)+→ λ(f : T → Bool)+→ λ(x : T)+→ merge { a = f } (< a : T >.a x) : Bool
dhall-lang/tests/normalization/success/unit/MergeWithTypeB.dhall view
@@ -1,1 +1,1 @@-y+λ(T : Type) → λ(f : T → Bool) → λ(x : T) → f x
dhall-lang/tests/normalization/success/unit/MergeWithTypeNormalizeArgumentsA.dhall view
@@ -1,1 +1,5 @@-merge (if True then x else y) (if True then z else b) : (if True then X else Y)+let id = λ(X : Type) → X++in    λ(x : { a : Bool })+    → λ(y : < a >)+    → merge (if True then x else x) (if True then y else y) : id Bool
dhall-lang/tests/normalization/success/unit/MergeWithTypeNormalizeArgumentsB.dhall view
@@ -1,1 +1,1 @@-merge x z : X+λ(x : { a : Bool }) → λ(y : < a >) → merge x y : Bool
dhall-lang/tests/normalization/success/unit/NaturalBuildFoldFusionA.dhall view
@@ -1,1 +1,1 @@-Natural/build (Natural/fold x)+λ(x : Natural) → Natural/build (Natural/fold x)
dhall-lang/tests/normalization/success/unit/NaturalBuildFoldFusionB.dhall view
@@ -1,1 +1,1 @@-x+λ(x : Natural) → Natural/fold x Natural (λ(x : Natural) → x + 1) 0
dhall-lang/tests/normalization/success/unit/NaturalBuildImplementationA.dhall view
@@ -1,2 +1,2 @@-Natural/build-(λ(natural : Type) → λ(succ : natural → natural) → λ(zero : natural) → x)+  λ(f : ∀(natural : Type) → (natural → natural) → natural → natural)+→ Natural/build f
dhall-lang/tests/normalization/success/unit/NaturalBuildImplementationB.dhall view
@@ -1,1 +1,2 @@-x+  λ(f : ∀(natural : Type) → (natural → natural) → natural → natural)+→ f Natural (λ(x : Natural) → x + 1) 0
dhall-lang/tests/normalization/success/unit/NaturalFoldOneA.dhall view
@@ -1,1 +1,1 @@-Natural/fold 1 Natural (λ(x : Natural) → 5) x+λ(x : Bool) → Natural/fold 1 Bool (λ(_ : Bool) → True) x
dhall-lang/tests/normalization/success/unit/NaturalFoldOneB.dhall view
@@ -1,1 +1,1 @@-5+λ(x : Bool) → True
dhall-lang/tests/normalization/success/unit/NaturalFoldZeroA.dhall view
@@ -1,1 +1,1 @@-Natural/fold 0 B g x+λ(x : Bool) → Natural/fold 0 Bool (λ(_ : Bool) → True) x
dhall-lang/tests/normalization/success/unit/NaturalFoldZeroB.dhall view
@@ -1,1 +1,1 @@-x+λ(x : Bool) → x
+ dhall-lang/tests/normalization/success/unit/NaturalSubtractEquivalentA.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → Natural/subtract x x
+ dhall-lang/tests/normalization/success/unit/NaturalSubtractEquivalentB.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → 0
+ dhall-lang/tests/normalization/success/unit/NaturalSubtractFromZeroA.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → Natural/subtract x 0
+ dhall-lang/tests/normalization/success/unit/NaturalSubtractFromZeroB.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → 0
+ dhall-lang/tests/normalization/success/unit/NaturalSubtractGreaterA.dhall view
@@ -0,0 +1,1 @@+Natural/subtract 3 10
+ dhall-lang/tests/normalization/success/unit/NaturalSubtractGreaterB.dhall view
@@ -0,0 +1,1 @@+7
+ dhall-lang/tests/normalization/success/unit/NaturalSubtractLessA.dhall view
@@ -0,0 +1,1 @@+Natural/subtract 3 2
+ dhall-lang/tests/normalization/success/unit/NaturalSubtractLessB.dhall view
@@ -0,0 +1,1 @@+0
+ dhall-lang/tests/normalization/success/unit/NaturalSubtractNormalizeA.dhall view
@@ -0,0 +1,3 @@+  λ(x : Natural)+→ λ(y : Natural)+→ Natural/subtract (if True then x else y) (10 + 20)
+ dhall-lang/tests/normalization/success/unit/NaturalSubtractNormalizeB.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → λ(y : Natural) → Natural/subtract x 30
+ dhall-lang/tests/normalization/success/unit/NaturalSubtractZero0A.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → Natural/subtract 0 x
+ dhall-lang/tests/normalization/success/unit/NaturalSubtractZero0B.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → x
+ dhall-lang/tests/normalization/success/unit/NaturalSubtractZero1A.dhall view
@@ -0,0 +1,1 @@+Natural/subtract 0
+ dhall-lang/tests/normalization/success/unit/NaturalSubtractZero1B.dhall view
@@ -0,0 +1,1 @@+Natural/subtract 0
+ dhall-lang/tests/normalization/success/unit/NestedRecordProjectionA.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool, b : Bool, c : Bool }) → x.{ a, b }.{ a }
+ dhall-lang/tests/normalization/success/unit/NestedRecordProjectionB.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool, b : Bool, c : Bool }) → x.{ a }
+ dhall-lang/tests/normalization/success/unit/NestedRecordProjectionByTypeA.dhall view
@@ -0,0 +1,2 @@+  λ(x : { a : Bool, b : Bool, c : Bool })+→ x.({ a : Bool, b : Bool }).({ a : Bool })
+ dhall-lang/tests/normalization/success/unit/NestedRecordProjectionByTypeB.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool, b : Bool, c : Bool }) → x.{ a }
− dhall-lang/tests/normalization/success/unit/NoneNaturalA.dhall
@@ -1,1 +0,0 @@-[] : Optional Natural
− dhall-lang/tests/normalization/success/unit/NoneNaturalB.dhall
@@ -1,1 +0,0 @@-None Natural
dhall-lang/tests/normalization/success/unit/OperatorAndEquivalentArgumentsA.dhall view
@@ -1,1 +1,1 @@-x && x+λ(x : Bool) → x && x
dhall-lang/tests/normalization/success/unit/OperatorAndEquivalentArgumentsB.dhall view
@@ -1,1 +1,1 @@-x+λ(x : Bool) → x
dhall-lang/tests/normalization/success/unit/OperatorAndLhsFalseA.dhall view
@@ -1,1 +1,1 @@-False && x+λ(x : Bool) → False && x
dhall-lang/tests/normalization/success/unit/OperatorAndLhsFalseB.dhall view
@@ -1,1 +1,1 @@-False+λ(x : Bool) → False
dhall-lang/tests/normalization/success/unit/OperatorAndLhsTrueA.dhall view
@@ -1,1 +1,1 @@-True && x+λ(x : Bool) → True && x
dhall-lang/tests/normalization/success/unit/OperatorAndLhsTrueB.dhall view
@@ -1,1 +1,1 @@-x+λ(x : Bool) → x
dhall-lang/tests/normalization/success/unit/OperatorAndNormalizeArgumentsA.dhall view
@@ -1,1 +1,1 @@-True && x && (True && y)+λ(x : Bool) → λ(y : Bool) → True && x && (True && y)
dhall-lang/tests/normalization/success/unit/OperatorAndNormalizeArgumentsB.dhall view
@@ -1,1 +1,1 @@-x && y+λ(x : Bool) → λ(y : Bool) → x && y
dhall-lang/tests/normalization/success/unit/OperatorAndRhsFalseA.dhall view
@@ -1,1 +1,1 @@-x && False+λ(x : Bool) → x && False
dhall-lang/tests/normalization/success/unit/OperatorAndRhsFalseB.dhall view
@@ -1,1 +1,1 @@-False+λ(x : Bool) → False
dhall-lang/tests/normalization/success/unit/OperatorAndRhsTrueA.dhall view
@@ -1,1 +1,1 @@-x && True+λ(x : Bool) → x && True
dhall-lang/tests/normalization/success/unit/OperatorAndRhsTrueB.dhall view
@@ -1,1 +1,1 @@-x+λ(x : Bool) → x
dhall-lang/tests/normalization/success/unit/OperatorEqualEquivalentArgumentsA.dhall view
@@ -1,1 +1,1 @@-x == x+λ(x : Bool) → x == x
dhall-lang/tests/normalization/success/unit/OperatorEqualEquivalentArgumentsB.dhall view
@@ -1,1 +1,1 @@-True+λ(x : Bool) → True
dhall-lang/tests/normalization/success/unit/OperatorEqualLhsTrueA.dhall view
@@ -1,1 +1,1 @@-x == True+λ(x : Bool) → x == True
dhall-lang/tests/normalization/success/unit/OperatorEqualLhsTrueB.dhall view
@@ -1,1 +1,1 @@-x+λ(x : Bool) → x
dhall-lang/tests/normalization/success/unit/OperatorEqualNormalizeArgumentsA.dhall view
@@ -1,1 +1,1 @@-True == x == (True == y)+λ(x : Bool) → λ(y : Bool) → True == x == (True == y)
dhall-lang/tests/normalization/success/unit/OperatorEqualNormalizeArgumentsB.dhall view
@@ -1,1 +1,1 @@-x == y+λ(x : Bool) → λ(y : Bool) → x == y
dhall-lang/tests/normalization/success/unit/OperatorEqualRhsTrueA.dhall view
@@ -1,1 +1,1 @@-True == x+λ(x : Bool) → True == x
dhall-lang/tests/normalization/success/unit/OperatorEqualRhsTrueB.dhall view
@@ -1,1 +1,1 @@-x+λ(x : Bool) → x
dhall-lang/tests/normalization/success/unit/OperatorListConcatenateLhsEmptyA.dhall view
@@ -1,1 +1,1 @@-x # ([] : List T)+λ(T : Type) → λ(x : List T) → x # ([] : List T)
dhall-lang/tests/normalization/success/unit/OperatorListConcatenateLhsEmptyB.dhall view
@@ -1,1 +1,1 @@-x+λ(T : Type) → λ(x : List T) → x
dhall-lang/tests/normalization/success/unit/OperatorListConcatenateListListA.dhall view
@@ -1,1 +1,1 @@-[ x ] # [ y ]+λ(T : Type) → λ(x : T) → λ(y : T) → [ x ] # [ y ]
dhall-lang/tests/normalization/success/unit/OperatorListConcatenateListListB.dhall view
@@ -1,1 +1,1 @@-[ x, y ]+λ(T : Type) → λ(x : T) → λ(y : T) → [ x, y ]
dhall-lang/tests/normalization/success/unit/OperatorListConcatenateNormalizeArgumentsA.dhall view
@@ -1,1 +1,4 @@-([] : List T) # x # (([] : List T) # y)+  λ(T : Type)+→ λ(x : List T)+→ λ(y : List T)+→ ([] : List T) # x # (([] : List T) # y)
dhall-lang/tests/normalization/success/unit/OperatorListConcatenateNormalizeArgumentsB.dhall view
@@ -1,1 +1,1 @@-x # y+λ(T : Type) → λ(x : List T) → λ(y : List T) → x # y
dhall-lang/tests/normalization/success/unit/OperatorListConcatenateRhsEmptyA.dhall view
@@ -1,1 +1,1 @@-([] : List T) # x+λ(T : Type) → λ(x : List T) → ([] : List T) # x
dhall-lang/tests/normalization/success/unit/OperatorListConcatenateRhsEmptyB.dhall view
@@ -1,1 +1,1 @@-x+λ(T : Type) → λ(x : List T) → x
dhall-lang/tests/normalization/success/unit/OperatorNotEqualEquivalentArgumentsA.dhall view
@@ -1,1 +1,1 @@-x != x+λ(x : Bool) → x != x
dhall-lang/tests/normalization/success/unit/OperatorNotEqualEquivalentArgumentsB.dhall view
@@ -1,1 +1,1 @@-False+λ(x : Bool) → False
dhall-lang/tests/normalization/success/unit/OperatorNotEqualLhsFalseA.dhall view
@@ -1,1 +1,1 @@-False != x+λ(x : Bool) → False != x
dhall-lang/tests/normalization/success/unit/OperatorNotEqualLhsFalseB.dhall view
@@ -1,1 +1,1 @@-x+λ(x : Bool) → x
dhall-lang/tests/normalization/success/unit/OperatorNotEqualNormalizeArgumentsA.dhall view
@@ -1,1 +1,1 @@-False != x != (False != y)+λ(x : Bool) → λ(y : Bool) → False != x != (False != y)
dhall-lang/tests/normalization/success/unit/OperatorNotEqualNormalizeArgumentsB.dhall view
@@ -1,1 +1,1 @@-x != y+λ(x : Bool) → λ(y : Bool) → x != y
dhall-lang/tests/normalization/success/unit/OperatorNotEqualRhsFalseA.dhall view
@@ -1,1 +1,1 @@-x != False+λ(x : Bool) → x != False
dhall-lang/tests/normalization/success/unit/OperatorNotEqualRhsFalseB.dhall view
@@ -1,1 +1,1 @@-x+λ(x : Bool) → x
dhall-lang/tests/normalization/success/unit/OperatorOrEquivalentArgumentsA.dhall view
@@ -1,1 +1,1 @@-x || x+λ(x : Bool) → x || x
dhall-lang/tests/normalization/success/unit/OperatorOrEquivalentArgumentsB.dhall view
@@ -1,1 +1,1 @@-x+λ(x : Bool) → x
dhall-lang/tests/normalization/success/unit/OperatorOrLhsFalseA.dhall view
@@ -1,1 +1,1 @@-False || x+λ(x : Bool) → False || x
dhall-lang/tests/normalization/success/unit/OperatorOrLhsFalseB.dhall view
@@ -1,1 +1,1 @@-x+λ(x : Bool) → x
dhall-lang/tests/normalization/success/unit/OperatorOrLhsTrueA.dhall view
@@ -1,1 +1,1 @@-True || x+λ(x : Bool) → True || x
dhall-lang/tests/normalization/success/unit/OperatorOrLhsTrueB.dhall view
@@ -1,1 +1,1 @@-True+λ(x : Bool) → True
dhall-lang/tests/normalization/success/unit/OperatorOrNormalizeArgumentsA.dhall view
@@ -1,1 +1,1 @@-False || x || (False || y)+λ(x : Bool) → λ(y : Bool) → False || x || (False || y)
dhall-lang/tests/normalization/success/unit/OperatorOrNormalizeArgumentsB.dhall view
@@ -1,1 +1,1 @@-x || y+λ(x : Bool) → λ(y : Bool) → x || y
dhall-lang/tests/normalization/success/unit/OperatorOrRhsFalseA.dhall view
@@ -1,1 +1,1 @@-x || False+λ(x : Bool) → x || False
dhall-lang/tests/normalization/success/unit/OperatorOrRhsFalseB.dhall view
@@ -1,1 +1,1 @@-x+λ(x : Bool) → x
dhall-lang/tests/normalization/success/unit/OperatorOrRhsTrueA.dhall view
@@ -1,1 +1,1 @@-x || True+λ(x : Bool) → x || True
dhall-lang/tests/normalization/success/unit/OperatorOrRhsTrueB.dhall view
@@ -1,1 +1,1 @@-True+λ(x : Bool) → True
dhall-lang/tests/normalization/success/unit/OperatorPlusLhsZeroA.dhall view
@@ -1,1 +1,1 @@-0 + x+λ(x : Natural) → 0 + x
dhall-lang/tests/normalization/success/unit/OperatorPlusLhsZeroB.dhall view
@@ -1,1 +1,1 @@-x+λ(x : Natural) → x
dhall-lang/tests/normalization/success/unit/OperatorPlusNormalizeArgumentsA.dhall view
@@ -1,1 +1,1 @@-0 + x + (0 + y)+λ(x : Natural) → λ(y : Natural) → 0 + x + (0 + y)
dhall-lang/tests/normalization/success/unit/OperatorPlusNormalizeArgumentsB.dhall view
@@ -1,1 +1,1 @@-x + y+λ(x : Natural) → λ(y : Natural) → x + y
dhall-lang/tests/normalization/success/unit/OperatorPlusRhsZeroA.dhall view
@@ -1,1 +1,1 @@-x + 0+λ(x : Natural) → x + 0
dhall-lang/tests/normalization/success/unit/OperatorPlusRhsZeroB.dhall view
@@ -1,1 +1,1 @@-x+λ(x : Natural) → x
dhall-lang/tests/normalization/success/unit/OperatorTextConcatenateLhsEmptyA.dhall view
@@ -1,1 +1,1 @@-"" ++ x+λ(x : Text) → "" ++ x
dhall-lang/tests/normalization/success/unit/OperatorTextConcatenateLhsEmptyB.dhall view
@@ -1,5 +1,1 @@-{- The expected result is not `"${x}"`, because the standard requires that any-   expression of the form `"${x}"` be simplified further to the equivalent-   expression `x`--}-x+λ(x : Text) → x
dhall-lang/tests/normalization/success/unit/OperatorTextConcatenateLhsNonEmptyA.dhall view
@@ -1,1 +1,1 @@-"hai" ++ x+λ(x : Text) → "hai" ++ x
dhall-lang/tests/normalization/success/unit/OperatorTextConcatenateLhsNonEmptyB.dhall view
@@ -1,1 +1,1 @@-"hai${x}"+λ(x : Text) → "hai${x}"
dhall-lang/tests/normalization/success/unit/OperatorTextConcatenateRhsEmptyA.dhall view
@@ -1,1 +1,1 @@-x ++ ""+λ(x : Text) → x ++ ""
dhall-lang/tests/normalization/success/unit/OperatorTextConcatenateRhsEmptyB.dhall view
@@ -1,5 +1,1 @@-{- The expected result is not `"${x}"`, because the standard requires that any-   expression of the form `"${x}"` be simplified further to the equivalent-   expression `x`--}-x+λ(x : Text) → x
dhall-lang/tests/normalization/success/unit/OperatorTextConcatenateRhsNonEmptyA.dhall view
@@ -1,1 +1,1 @@-x ++ "hai"+λ(x : Text) → x ++ "hai"
dhall-lang/tests/normalization/success/unit/OperatorTextConcatenateRhsNonEmptyB.dhall view
@@ -1,1 +1,1 @@-"${x}hai"+λ(x : Text) → "${x}hai"
dhall-lang/tests/normalization/success/unit/OperatorTimesLhsOneA.dhall view
@@ -1,1 +1,1 @@-1 * x+λ(x : Natural) → 1 * x
dhall-lang/tests/normalization/success/unit/OperatorTimesLhsOneB.dhall view
@@ -1,1 +1,1 @@-x+λ(x : Natural) → x
dhall-lang/tests/normalization/success/unit/OperatorTimesLhsZeroA.dhall view
@@ -1,1 +1,1 @@-0 * x+λ(x : Natural) → 0 * x
dhall-lang/tests/normalization/success/unit/OperatorTimesLhsZeroB.dhall view
@@ -1,1 +1,1 @@-0+λ(x : Natural) → 0
dhall-lang/tests/normalization/success/unit/OperatorTimesNormalizeArgumentsA.dhall view
@@ -1,1 +1,1 @@-1 * x * (1 * y)+λ(x : Natural) → λ(y : Natural) → 1 * x * (1 * y)
dhall-lang/tests/normalization/success/unit/OperatorTimesNormalizeArgumentsB.dhall view
@@ -1,1 +1,1 @@-x * y+λ(x : Natural) → λ(y : Natural) → x * y
dhall-lang/tests/normalization/success/unit/OperatorTimesRhsOneA.dhall view
@@ -1,1 +1,1 @@-x * 1+λ(x : Natural) → x * 1
dhall-lang/tests/normalization/success/unit/OperatorTimesRhsOneB.dhall view
@@ -1,1 +1,1 @@-x+λ(x : Natural) → x
dhall-lang/tests/normalization/success/unit/OperatorTimesRhsZeroA.dhall view
@@ -1,1 +1,1 @@-x * 0+λ(x : Natural) → x * 0
dhall-lang/tests/normalization/success/unit/OperatorTimesRhsZeroB.dhall view
@@ -1,1 +1,1 @@-0+λ(x : Natural) → 0
− 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 @@-Optional/build A0 (Optional/fold A1 x)
− dhall-lang/tests/normalization/success/unit/OptionalBuildFoldFusionB.dhall
@@ -1,1 +0,0 @@-x
− dhall-lang/tests/normalization/success/unit/OptionalBuildImplementationA.dhall
@@ -1,3 +0,0 @@-Optional/build-A-(λ(optional : Type) → λ(just : A → optional) → λ(nothing : optional) → x)
− dhall-lang/tests/normalization/success/unit/OptionalBuildImplementationB.dhall
@@ -1,1 +0,0 @@-x
− 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 @@-Optional/fold A (None A) B (λ(_ : A) → _) x
− dhall-lang/tests/normalization/success/unit/OptionalFoldNoneB.dhall
@@ -1,1 +0,0 @@-x
− dhall-lang/tests/normalization/success/unit/OptionalFoldSomeA.dhall
@@ -1,1 +0,0 @@-Optional/fold A (Some x) B (λ(_ : A) → _) z
− dhall-lang/tests/normalization/success/unit/OptionalFoldSomeB.dhall
@@ -1,1 +0,0 @@-x
dhall-lang/tests/normalization/success/unit/RecordA.dhall view
@@ -1,1 +1,1 @@-{ a : if True then y else z, b : x }+λ(x : Bool) → { a = if True then x else x, b = x }
dhall-lang/tests/normalization/success/unit/RecordB.dhall view
@@ -1,1 +1,1 @@-{ a : y, b : x }+λ(x : Bool) → { a = x, b = x }
+ dhall-lang/tests/normalization/success/unit/RecordLitAllSugarsA.dhall view
@@ -0,0 +1,1 @@+let x = { y = 1 } in { x, x.z = 2 }
+ dhall-lang/tests/normalization/success/unit/RecordLitAllSugarsB.dhall view
@@ -0,0 +1,1 @@+{ x = { y = 1, z = 2 } }
+ dhall-lang/tests/normalization/success/unit/RecordLitDottedFieldsA.dhall view
@@ -0,0 +1,1 @@+{ x.y.z = True }
+ dhall-lang/tests/normalization/success/unit/RecordLitDottedFieldsB.dhall view
@@ -0,0 +1,1 @@+{ x = { y = { z = True } } }
+ dhall-lang/tests/normalization/success/unit/RecordLitDuplicateFieldsNoCollisionsA.dhall view
@@ -0,0 +1,9 @@+{-  This expression desugars to:++        { x = { y = 0 } ∧ { z = 0 } }++    ... which then β-normalizes to:++        { x = { y = 0, z = 0 } }+-}+{ x = { y = 0 }, x = { z = 0 } }
+ dhall-lang/tests/normalization/success/unit/RecordLitDuplicateFieldsNoCollisionsB.dhall view
@@ -0,0 +1,1 @@+{ x = { y = 0, z = 0 } }
+ dhall-lang/tests/normalization/success/unit/RecordLitNixLikeA.dhall view
@@ -0,0 +1,4 @@+{- The purpose of this test is to verify that the Nix-like idiom of setting+   multiple overlapping dotted fields works correctly+-}+{ x.y = 1, x.z = True }
+ dhall-lang/tests/normalization/success/unit/RecordLitNixLikeB.dhall view
@@ -0,0 +1,1 @@+{ x = { y = 1, z = True } }
+ dhall-lang/tests/normalization/success/unit/RecordLitPun1A.dhall view
@@ -0,0 +1,1 @@+let x = 0 in { x }
+ dhall-lang/tests/normalization/success/unit/RecordLitPun1B.dhall view
@@ -0,0 +1,1 @@+{ x = 0 }
+ dhall-lang/tests/normalization/success/unit/RecordLitPun2A.dhall view
@@ -0,0 +1,1 @@+let x = 0 let y = 1 in { x, y, z = 2 }
+ dhall-lang/tests/normalization/success/unit/RecordLitPun2B.dhall view
@@ -0,0 +1,1 @@+{ x = 0, y = 1, z = 2 }
+ dhall-lang/tests/normalization/success/unit/RecordLitTriplicateFieldsA.dhall view
@@ -0,0 +1,7 @@+{-  This test ensures that an implementation handles more than one duplicate+    field correctly and combines them with the correct order and associativity+-}+  λ(a : { x : Natural })+→ λ(b : { y : Natural })+→ λ(c : { z : Natural })+→ { k = a, k = b, k = c }
+ dhall-lang/tests/normalization/success/unit/RecordLitTriplicateFieldsB.dhall view
@@ -0,0 +1,4 @@+  λ(a : { x : Natural })+→ λ(b : { y : Natural })+→ λ(c : { z : Natural })+→ { k = a ∧ b ∧ c }
dhall-lang/tests/normalization/success/unit/RecordProjectionA.dhall view
@@ -1,1 +1,1 @@-{ x = a, y = b, z = c }.{ x, z }+{ x = 1, y = 2, z = 3 }.{ x, z }
dhall-lang/tests/normalization/success/unit/RecordProjectionB.dhall view
@@ -1,1 +1,1 @@-{ x = a, z = c }+{ x = 1, z = 3 }
+ dhall-lang/tests/normalization/success/unit/RecordProjectionByTypeEmptyA.dhall view
@@ -0,0 +1,1 @@+{ a = 10, b = Some 10 }.({})
+ dhall-lang/tests/normalization/success/unit/RecordProjectionByTypeEmptyB.dhall view
@@ -0,0 +1,1 @@+{=}
+ dhall-lang/tests/normalization/success/unit/RecordProjectionByTypeNonEmptyA.dhall view
@@ -0,0 +1,1 @@+{ a = 10, b = Some 10, c = [ "text" ]}.({ a : Natural, b : Optional Natural })
+ dhall-lang/tests/normalization/success/unit/RecordProjectionByTypeNonEmptyB.dhall view
@@ -0,0 +1,1 @@+{ a = 10, b = Some 10 }
+ dhall-lang/tests/normalization/success/unit/RecordProjectionByTypeNormalizeProjectionA.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool, b : Bool, c : Bool }) → x.({ a : Bool, b : Bool })
+ dhall-lang/tests/normalization/success/unit/RecordProjectionByTypeNormalizeProjectionB.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool, b : Bool, c : Bool }) → x.{ a, b }
+ dhall-lang/tests/normalization/success/unit/RecordProjectionByTypeWithinFieldSelectionA.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool, b : Bool, c : Bool }) → x.({ a : Bool, b : Bool }).a
+ dhall-lang/tests/normalization/success/unit/RecordProjectionByTypeWithinFieldSelectionB.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool, b : Bool, c : Bool }) → x.a
dhall-lang/tests/normalization/success/unit/RecordProjectionEmptyA.dhall view
@@ -1,1 +1,1 @@-x.{}+λ(x : { a : Bool }) → x.{}
dhall-lang/tests/normalization/success/unit/RecordProjectionEmptyB.dhall view
@@ -1,1 +1,1 @@-{=}+λ(x : { a : Bool }) → {=}
dhall-lang/tests/normalization/success/unit/RecordProjectionNormalizeArgumentsA.dhall view
@@ -1,1 +1,1 @@-(if True then y else z).{ x, y }+λ(x : { a : Bool, b : Bool, c : Bool }) → (if True then x else x).{ a, b }
dhall-lang/tests/normalization/success/unit/RecordProjectionNormalizeArgumentsB.dhall view
@@ -1,1 +1,1 @@-y.{ x, y }+λ(x : { a : Bool, b : Bool, c : Bool }) → x.{ a, b }
+ dhall-lang/tests/normalization/success/unit/RecordProjectionNormalizeFieldsA.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool, b : Bool, c : Bool }) → x.{ c, a }
+ dhall-lang/tests/normalization/success/unit/RecordProjectionNormalizeFieldsB.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool, b : Bool, c : Bool }) → x.{ a, c }
− dhall-lang/tests/normalization/success/unit/RecordProjectionTypeEmptyA.dhall
@@ -1,1 +0,0 @@-{ a = 10, b = Some 10 }.({})
− dhall-lang/tests/normalization/success/unit/RecordProjectionTypeEmptyB.dhall
@@ -1,1 +0,0 @@-{=}
− dhall-lang/tests/normalization/success/unit/RecordProjectionTypeNonEmptyA.dhall
@@ -1,1 +0,0 @@-{ a = 10, b = Some 10, c = [ "text" ]}.({ a : Natural, b : Optional Natural })
− dhall-lang/tests/normalization/success/unit/RecordProjectionTypeNonEmptyB.dhall
@@ -1,1 +0,0 @@-{ a = 10, b = Some 10 }
+ dhall-lang/tests/normalization/success/unit/RecordProjectionWithinFieldSelectionA.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool, b : Bool, c : Bool }) → x.{ a, b }.a
+ dhall-lang/tests/normalization/success/unit/RecordProjectionWithinFieldSelectionB.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool, b : Bool, c : Bool }) → x.a
dhall-lang/tests/normalization/success/unit/RecordSelectionA.dhall view
@@ -1,1 +1,1 @@-{ x = v }.x+λ(x : Bool) → { a = x }.a
dhall-lang/tests/normalization/success/unit/RecordSelectionB.dhall view
@@ -1,1 +1,1 @@-v+λ(x : Bool) → x
dhall-lang/tests/normalization/success/unit/RecordSelectionNormalizeArgumentsA.dhall view
@@ -1,1 +1,1 @@-(if True then y else z).x+λ(x : { a : Bool }) → λ(y : { a : Bool }) → (if True then x else y).a
dhall-lang/tests/normalization/success/unit/RecordSelectionNormalizeArgumentsB.dhall view
@@ -1,1 +1,1 @@-y.x+λ(x : { a : Bool }) → λ(y : { a : Bool }) → x.a
+ dhall-lang/tests/normalization/success/unit/RecordSortFieldsA.dhall view
@@ -0,0 +1,1 @@+{ b = 1, a = 0 }
+ dhall-lang/tests/normalization/success/unit/RecordSortFieldsB.dhall view
@@ -0,0 +1,1 @@+{ a = 0, b = 1 }
dhall-lang/tests/normalization/success/unit/RecordTypeA.dhall view
@@ -1,1 +1,1 @@-{ a : if True then A else B, b : T }+let id = λ(X : Type) → X in λ(T : Type) → { a : id Bool, b : T }
dhall-lang/tests/normalization/success/unit/RecordTypeB.dhall view
@@ -1,1 +1,1 @@-{ a : A, b : T }+λ(T : Type) → { a : Bool, b : T }
+ 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/RecursiveRecordMergeLhsEmptyA.dhall view
@@ -1,1 +1,1 @@-{=} ∧ x+λ(x : { a : Bool }) → {=} ∧ x
dhall-lang/tests/normalization/success/unit/RecursiveRecordMergeLhsEmptyB.dhall view
@@ -1,1 +1,1 @@-x+λ(x : { a : Bool }) → x
dhall-lang/tests/normalization/success/unit/RecursiveRecordMergeNoCollisionA.dhall view
@@ -1,1 +1,1 @@-{ x = { z = 1 } } ∧ { b = { y = 2 } }+{ x = { a = 1 } } ∧ { y = { b = 2 } }
dhall-lang/tests/normalization/success/unit/RecursiveRecordMergeNoCollisionB.dhall view
@@ -1,1 +1,1 @@-{ b = { y = 2 }, x = { z = 1 } }+{ x = { a = 1 }, y = { b = 2 } }
dhall-lang/tests/normalization/success/unit/RecursiveRecordMergeNormalizeArgumentsA.dhall view
@@ -1,1 +1,1 @@-x ∧ {=} ∧ ({=} ∧ b)+λ(x : { a : Bool }) → λ(y : { b : Bool }) → x ∧ {=} ∧ ({=} ∧ y)
dhall-lang/tests/normalization/success/unit/RecursiveRecordMergeNormalizeArgumentsB.dhall view
@@ -1,1 +1,1 @@-x ∧ b+λ(x : { a : Bool }) → λ(y : { b : Bool }) → x ∧ y
dhall-lang/tests/normalization/success/unit/RecursiveRecordMergeRhsEmptyA.dhall view
@@ -1,1 +1,1 @@-x ∧ {=}+λ(x : { a : Bool }) → x ∧ {=}
dhall-lang/tests/normalization/success/unit/RecursiveRecordMergeRhsEmptyB.dhall view
@@ -1,1 +1,1 @@-x+λ(x : { a : Bool }) → x
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordMergeWithinFieldSelection0A.dhall view
@@ -0,0 +1,1 @@+λ(x : { c : Bool }) → (x ∧ { a = 0, b = 1 }).a
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordMergeWithinFieldSelection0B.dhall view
@@ -0,0 +1,1 @@+λ(x : { c : Bool }) → (x ∧ { a = 0 }).a
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordMergeWithinFieldSelection1A.dhall view
@@ -0,0 +1,1 @@+λ(x : { b : Bool }) → (x ∧ { a = 1 }).b
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordMergeWithinFieldSelection1B.dhall view
@@ -0,0 +1,1 @@+λ(x : { b : Bool }) → x.b
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordMergeWithinFieldSelection2A.dhall view
@@ -0,0 +1,1 @@+λ(x : { b : Bool }) → ({ a = 1 } ∧ x).b
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordMergeWithinFieldSelection2B.dhall view
@@ -0,0 +1,1 @@+λ(x : { b : Bool }) → x.b
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordMergeWithinFieldSelection3A.dhall view
@@ -0,0 +1,1 @@+λ(x : { c : Bool }) → ({ a = 0, b = 1 } ∧ x).a
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordMergeWithinFieldSelection3B.dhall view
@@ -0,0 +1,1 @@+λ(x : { c : Bool }) → ({ a = 0 } ∧ x).a
dhall-lang/tests/normalization/success/unit/RecursiveRecordTypeMergeCollisionA.dhall view
@@ -1,1 +1,1 @@-{ x : { z : A } } ⩓ { x : { y : B } }+{ x : { z : Bool } } ⩓ { x : { y : Natural } }
dhall-lang/tests/normalization/success/unit/RecursiveRecordTypeMergeCollisionB.dhall view
@@ -1,1 +1,1 @@-{ x : { y : B, z : A } }+{ x : { y : Natural, z : Bool } }
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordTypeMergeDeepA.dhall view
@@ -0,0 +1,1 @@+{ a : { b : { x : Bool } } } ⩓ { a : { b : { y : Bool } } }
+ dhall-lang/tests/normalization/success/unit/RecursiveRecordTypeMergeDeepB.dhall view
@@ -0,0 +1,1 @@+{ a : { b : { x : Bool, y : Bool } } }
dhall-lang/tests/normalization/success/unit/RecursiveRecordTypeMergeLhsEmptyA.dhall view
@@ -1,1 +1,1 @@-{} ⩓ x+{} ⩓ { a : Bool }
dhall-lang/tests/normalization/success/unit/RecursiveRecordTypeMergeLhsEmptyB.dhall view
@@ -1,1 +1,1 @@-x+{ a : Bool }
dhall-lang/tests/normalization/success/unit/RecursiveRecordTypeMergeNoCollisionA.dhall view
@@ -1,1 +1,1 @@-{ x : { z : A } } ⩓ { b : { y : B } }+{ x : { a : Bool } } ⩓ { y : { b : Natural } }
dhall-lang/tests/normalization/success/unit/RecursiveRecordTypeMergeNoCollisionB.dhall view
@@ -1,1 +1,1 @@-{ b : { y : B }, x : { z : A } }+{ x : { a : Bool }, y : { b : Natural } }
dhall-lang/tests/normalization/success/unit/RecursiveRecordTypeMergeNormalizeArgumentsA.dhall view
@@ -1,1 +1,1 @@-x ⩓ {} ⩓ ({} ⩓ b)+{ a : Bool } ⩓ {} ⩓ ({} ⩓ { b : Bool })
dhall-lang/tests/normalization/success/unit/RecursiveRecordTypeMergeNormalizeArgumentsB.dhall view
@@ -1,1 +1,1 @@-x ⩓ b+{ a : Bool, b : Bool }
dhall-lang/tests/normalization/success/unit/RecursiveRecordTypeMergeRhsEmptyA.dhall view
@@ -1,1 +1,1 @@-x ⩓ {}+{ a : Bool } ⩓ {}
dhall-lang/tests/normalization/success/unit/RecursiveRecordTypeMergeRhsEmptyB.dhall view
@@ -1,1 +1,1 @@-x+{ a : Bool }
+ dhall-lang/tests/normalization/success/unit/RightBiasedMergeEquivalentArgumentsA.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool }) → x ⫽ x
+ dhall-lang/tests/normalization/success/unit/RightBiasedMergeEquivalentArgumentsB.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool }) → x
+ dhall-lang/tests/normalization/success/unit/RightBiasedMergeWithinFieldSelection0A.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool }) → (x ⫽ { a = 0 }).a
+ dhall-lang/tests/normalization/success/unit/RightBiasedMergeWithinFieldSelection0B.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool }) → 0
+ dhall-lang/tests/normalization/success/unit/RightBiasedMergeWithinFieldSelection1A.dhall view
@@ -0,0 +1,1 @@+λ(x : { b : Bool }) → (x ⫽ { a = 0 }).b
+ dhall-lang/tests/normalization/success/unit/RightBiasedMergeWithinFieldSelection1B.dhall view
@@ -0,0 +1,1 @@+λ(x : { b : Bool }) → x.b
+ dhall-lang/tests/normalization/success/unit/RightBiasedMergeWithinFieldSelection2A.dhall view
@@ -0,0 +1,1 @@+λ(x : { b : Bool }) → λ(y : Bool) → ({ a = y } ⫽ x).b
+ dhall-lang/tests/normalization/success/unit/RightBiasedMergeWithinFieldSelection2B.dhall view
@@ -0,0 +1,1 @@+λ(x : { b : Bool }) → λ(y : Bool) → x.b
+ dhall-lang/tests/normalization/success/unit/RightBiasedMergeWithinFieldSelection3A.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool }) → ({ a = 0, b = 1 } ⫽ x).a
+ dhall-lang/tests/normalization/success/unit/RightBiasedMergeWithinFieldSelection3B.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : Bool }) → ({ a = 0 } ⫽ x).a
dhall-lang/tests/normalization/success/unit/RightBiasedRecordMergeLhsEmptyA.dhall view
@@ -1,1 +1,1 @@-{=} ⫽ x+λ(x : { a : Bool }) → {=} ⫽ x
dhall-lang/tests/normalization/success/unit/RightBiasedRecordMergeLhsEmptyB.dhall view
@@ -1,1 +1,1 @@-x+λ(x : { a : Bool }) → x
dhall-lang/tests/normalization/success/unit/RightBiasedRecordMergeNormalizeArgumentsA.dhall view
@@ -1,1 +1,1 @@-x ⫽ {=} ⫽ (y ⫽ {=})+λ(x : { a : Bool }) → λ(y : { a : Bool }) → x ⫽ {=} ⫽ (y ⫽ {=})
dhall-lang/tests/normalization/success/unit/RightBiasedRecordMergeNormalizeArgumentsB.dhall view
@@ -1,1 +1,1 @@-x ⫽ y+λ(x : { a : Bool }) → λ(y : { a : Bool }) → x ⫽ y
dhall-lang/tests/normalization/success/unit/RightBiasedRecordMergeRhsEmptyA.dhall view
@@ -1,1 +1,1 @@-x ⫽ {=}+λ(x : { a : Bool }) → x ⫽ {=}
dhall-lang/tests/normalization/success/unit/RightBiasedRecordMergeRhsEmptyB.dhall view
@@ -1,1 +1,1 @@-x+λ(x : { a : Bool }) → x
+ dhall-lang/tests/normalization/success/unit/RightBiasedRecordMergeWithinRecordProjectionA.dhall view
@@ -0,0 +1,1 @@+λ(x : { c : Natural }) → (x ⫽ { a = 1, b = 2 }).{ a, c }
+ dhall-lang/tests/normalization/success/unit/RightBiasedRecordMergeWithinRecordProjectionB.dhall view
@@ -0,0 +1,1 @@+λ(x : { c : Natural }) → x.{ c } ⫽ { a = 1 }
+ dhall-lang/tests/normalization/success/unit/ShowConstructorEmptyA.dhall view
@@ -0,0 +1,1 @@+showConstructor <A>.A
+ dhall-lang/tests/normalization/success/unit/ShowConstructorEmptyB.dhall view
@@ -0,0 +1,1 @@+"A"
+ dhall-lang/tests/normalization/success/unit/ShowConstructorNonEmptyA.dhall view
@@ -0,0 +1,1 @@+showConstructor (< A : Bool>.A False)
+ dhall-lang/tests/normalization/success/unit/ShowConstructorNonEmptyB.dhall view
@@ -0,0 +1,1 @@+"A"
dhall-lang/tests/normalization/success/unit/SomeNormalizeArgumentsA.dhall view
@@ -1,1 +1,1 @@-Some (if True then x else y)+λ(x : Bool) → λ(y : Bool) → Some (if True then x else y)
dhall-lang/tests/normalization/success/unit/SomeNormalizeArgumentsB.dhall view
@@ -1,1 +1,1 @@-Some x+λ(x : Bool) → λ(y : Bool) → Some x
dhall-lang/tests/normalization/success/unit/TextInterpolateA.dhall view
@@ -1,1 +1,1 @@-"s${"b${x}"}"+λ(x : Text) → "s${"b${x}"}"
dhall-lang/tests/normalization/success/unit/TextInterpolateB.dhall view
@@ -1,1 +1,1 @@-"sb${x}"+λ(x : Text) → "sb${x}"
+ dhall-lang/tests/normalization/success/unit/TextLitNested1A.dhall view
@@ -0,0 +1,1 @@+λ(x: Text) → "${""}${x}"
+ dhall-lang/tests/normalization/success/unit/TextLitNested1B.dhall view
@@ -0,0 +1,1 @@+λ(x : Text) → x
+ dhall-lang/tests/normalization/success/unit/TextLitNested2A.dhall view
@@ -0,0 +1,1 @@+λ(x: Text) → "${"${x}"}"
+ dhall-lang/tests/normalization/success/unit/TextLitNested2B.dhall view
@@ -0,0 +1,1 @@+λ(x : Text) → x
+ dhall-lang/tests/normalization/success/unit/TextLitNested3A.dhall view
@@ -0,0 +1,1 @@+λ(x: Text) → "${"${""}"}${x}"
+ dhall-lang/tests/normalization/success/unit/TextLitNested3B.dhall view
@@ -0,0 +1,1 @@+λ(x : Text) → x
dhall-lang/tests/normalization/success/unit/TextNormalizeInterpolationsA.dhall view
@@ -1,1 +1,1 @@-"s${if True then x else y}"+λ(x : Text) → λ(y : Text) → "s${if True then x else y}"
dhall-lang/tests/normalization/success/unit/TextNormalizeInterpolationsB.dhall view
@@ -1,1 +1,1 @@-"s${x}"+λ(x : Text) → λ(y : Text) → "s${x}"
+ dhall-lang/tests/normalization/success/unit/TextReplaceAbstractA.dhall view
@@ -0,0 +1,3 @@+{- This test verifies that an implementation works with an abstract "replacement".+-}+λ(x : Text) → Text/replace "a" "-${x}-" "_a__a_"
+ dhall-lang/tests/normalization/success/unit/TextReplaceAbstractB.dhall view
@@ -0,0 +1,1 @@+λ(x : Text) → "_-${x}-__-${x}-_"
+ dhall-lang/tests/normalization/success/unit/TextReplaceAbstractHaystackA.dhall view
@@ -0,0 +1,4 @@+{- This test verifies that an implementation does not beta normalize with an+   abstract "haystack".+-}+λ(x : Text) → λ(y : Text) → Text/replace "a" "-${x}-" "_a_${y}_a_"
+ dhall-lang/tests/normalization/success/unit/TextReplaceAbstractHaystackB.dhall view
@@ -0,0 +1,1 @@+λ(x : Text) → λ(y : Text) → Text/replace "a" "-${x}-" "_a_${y}_a_"
+ dhall-lang/tests/normalization/success/unit/TextReplaceEmpty1A.dhall view
@@ -0,0 +1,1 @@+Text/replace ""
+ dhall-lang/tests/normalization/success/unit/TextReplaceEmpty1B.dhall view
@@ -0,0 +1,1 @@+Text/replace ""
+ dhall-lang/tests/normalization/success/unit/TextReplaceEmpty2A.dhall view
@@ -0,0 +1,2 @@+λ(replacement : Text) →+  Text/replace "" replacement
+ dhall-lang/tests/normalization/success/unit/TextReplaceEmpty2B.dhall view
@@ -0,0 +1,2 @@+λ(replacement : Text) →+  Text/replace "" replacement
+ dhall-lang/tests/normalization/success/unit/TextReplaceEmpty3A.dhall view
@@ -0,0 +1,3 @@+λ(replacement : Text) →+λ(haystack : Text) →+  Text/replace "" replacement haystack
+ dhall-lang/tests/normalization/success/unit/TextReplaceEmpty3B.dhall view
@@ -0,0 +1,1 @@+λ(replacement : Text) → λ(haystack : Text) → haystack
+ dhall-lang/tests/normalization/success/unit/TextReplaceMultipleA.dhall view
@@ -0,0 +1,1 @@+Text/replace "foo" "bar" "foobazfoo"
+ dhall-lang/tests/normalization/success/unit/TextReplaceMultipleB.dhall view
@@ -0,0 +1,1 @@+"barbazbar"
+ dhall-lang/tests/normalization/success/unit/TextReplaceNFCUnicodeA.dhall view
@@ -0,0 +1,1 @@+Text/replace "👨" "👩" "👨‍👩‍👧‍👦"
+ dhall-lang/tests/normalization/success/unit/TextReplaceNFCUnicodeB.dhall view
@@ -0,0 +1,1 @@+"👩‍👩‍👧‍👦"
+ dhall-lang/tests/normalization/success/unit/TextReplaceNormalizationA.dhall view
@@ -0,0 +1,3 @@+-- This test verifies that implementations do not perform Unicode normalization+-- before substitution.+Text/replace "a\u{0301}" "b" "\u{00e1}c"
+ dhall-lang/tests/normalization/success/unit/TextReplaceNormalizationB.dhall view
@@ -0,0 +1,1 @@+"ác"
+ dhall-lang/tests/normalization/success/unit/TextReplaceOverlappingA.dhall view
@@ -0,0 +1,1 @@+Text/replace "aa" "b" "aaaaa"
+ dhall-lang/tests/normalization/success/unit/TextReplaceOverlappingB.dhall view
@@ -0,0 +1,1 @@+"bba"
+ dhall-lang/tests/normalization/success/unit/TextReplaceSimpleA.dhall view
@@ -0,0 +1,1 @@+Text/replace "foo" "bar" "foo"
+ dhall-lang/tests/normalization/success/unit/TextReplaceSimpleB.dhall view
@@ -0,0 +1,1 @@+"bar"
+ dhall-lang/tests/normalization/success/unit/TextReplaceUnicodeA.dhall view
@@ -0,0 +1,1 @@+Text/replace "💣" "💥" "💣💣💣"
+ dhall-lang/tests/normalization/success/unit/TextReplaceUnicodeB.dhall view
@@ -0,0 +1,1 @@+"💥💥💥"
+ dhall-lang/tests/normalization/success/unit/TextReplaceVarA.dhall view
@@ -0,0 +1,3 @@+{- This test verifies that an implementation works with a variable as "replacement".+-}+λ(x : Text) → Text/replace "a" x "aaa"
+ dhall-lang/tests/normalization/success/unit/TextReplaceVarB.dhall view
@@ -0,0 +1,1 @@+λ(x : Text) → "${x}${x}${x}"
+ dhall-lang/tests/normalization/success/unit/TextShowEmptyA.dhall view
@@ -0,0 +1,1 @@+Text/show ""
+ dhall-lang/tests/normalization/success/unit/TextShowEmptyB.dhall view
@@ -0,0 +1,1 @@+"\"\""
dhall-lang/tests/normalization/success/unit/TextShowInterpolatedA.dhall view
@@ -1,1 +1,1 @@-Text/show "text ${with} interpolation"+λ(containing : Text) → Text/show "text ${containing} interpolation"
dhall-lang/tests/normalization/success/unit/TextShowInterpolatedB.dhall view
@@ -1,1 +1,1 @@-Text/show "text ${with} interpolation"+λ(containing: Text) → Text/show "text ${containing} interpolation"
+ dhall-lang/tests/normalization/success/unit/TimeAsRecordA.dhall view
@@ -0,0 +1,2 @@+-- Timestamps are records, and this is a no-op+2000-01-01T12:00:00+08:00.{ time, date, timeZone }
+ dhall-lang/tests/normalization/success/unit/TimeAsRecordB.dhall view
@@ -0,0 +1,1 @@+2000-01-01T12:00:00+08:00
+ dhall-lang/tests/normalization/success/unit/ToMapA.dhall view
@@ -0,0 +1,1 @@+toMap { foo= 1, bar= 4, baz= 9 }
+ dhall-lang/tests/normalization/success/unit/ToMapB.dhall view
@@ -0,0 +1,4 @@+[ { mapKey = "bar", mapValue = 4 }+, { mapKey = "baz", mapValue = 9 }+, { mapKey = "foo", mapValue = 1 }+]
+ dhall-lang/tests/normalization/success/unit/ToMapWithTypeA.dhall view
@@ -0,0 +1,16 @@+{- This test verifies that the normalized result does not contain a type+   annotation if the input record is non-empty.++   The reason for this test is that implementations might need to store+   optional type annotations for both `toMap` invocations and empty list+   literals.  If an implementation does so, a common mistake is to take+   the optional type annotation and always pass it through as the optional+   type annotation for the list literal that `toMap` generates.++   However, the standard specifies that `toMap` should only generate a+   type annotation if the input record is empty.  If the input record is+   non-empty then the resulting normalized list is non-empty and therefore+   should not have a type annotation (since a non-empty list with a type+   annotation is not in normal form).+-}+toMap { foo= 1, bar= 4, baz= 9 } : List { mapKey : Text, mapValue : Natural }
+ dhall-lang/tests/normalization/success/unit/ToMapWithTypeB.dhall view
@@ -0,0 +1,4 @@+[ { mapKey = "bar", mapValue = 4 }+, { mapKey = "baz", mapValue = 9 }+, { mapKey = "foo", mapValue = 1 }+]
dhall-lang/tests/normalization/success/unit/TypeAnnotationA.dhall view
@@ -1,1 +1,1 @@-x : A+λ(x : Bool) → x : Bool
dhall-lang/tests/normalization/success/unit/TypeAnnotationB.dhall view
@@ -1,1 +1,1 @@-x+λ(x : Bool) → x
− dhall-lang/tests/normalization/success/unit/UnionLiteralNormalizeAlternativesA.dhall
@@ -1,1 +0,0 @@-< x = y | y : if True then X else Y | z >
− dhall-lang/tests/normalization/success/unit/UnionLiteralNormalizeAlternativesB.dhall
@@ -1,1 +0,0 @@-< x = y | y : X | z >
− dhall-lang/tests/normalization/success/unit/UnionLiteralNormalizeArgumentsA.dhall
@@ -1,1 +0,0 @@-< x = if True then y else z >
− dhall-lang/tests/normalization/success/unit/UnionLiteralNormalizeArgumentsB.dhall
@@ -1,1 +0,0 @@-< x = y >
− dhall-lang/tests/normalization/success/unit/UnionLiteralSortAlternativesA.dhall
@@ -1,1 +0,0 @@-< x = y | z | y : B >
− dhall-lang/tests/normalization/success/unit/UnionLiteralSortAlternativesB.dhall
@@ -1,1 +0,0 @@-< x = y | y : B | z >
dhall-lang/tests/normalization/success/unit/UnionProjectConstructorA.dhall view
@@ -1,1 +1,1 @@-< x : T >.x+< x : Bool >.x
dhall-lang/tests/normalization/success/unit/UnionProjectConstructorB.dhall view
@@ -1,1 +1,1 @@-< x : T >.x+< x : Bool >.x
dhall-lang/tests/normalization/success/unit/UnionTypeA.dhall view
@@ -1,1 +1,1 @@-< x : B | z >+< x : Bool | z >
dhall-lang/tests/normalization/success/unit/UnionTypeB.dhall view
@@ -1,1 +1,1 @@-< x : B | z >+< x : Bool | z >
dhall-lang/tests/normalization/success/unit/UnionTypeNormalizeArgumentsA.dhall view
@@ -1,1 +1,1 @@-< x : if True then B else Z | z >+let id = λ(X : Type) → X in < x : id Bool | z >
dhall-lang/tests/normalization/success/unit/UnionTypeNormalizeArgumentsB.dhall view
@@ -1,1 +1,1 @@-< x : B | z >+< x : Bool | z >
dhall-lang/tests/normalization/success/unit/VariableA.dhall view
@@ -1,1 +1,1 @@-x+λ(x : Bool) → x
dhall-lang/tests/normalization/success/unit/VariableB.dhall view
@@ -1,1 +1,1 @@-x+λ(x : Bool) → x
+ dhall-lang/tests/normalization/success/unit/WithA.dhall view
@@ -0,0 +1,1 @@+{ a = 1 } with b = 2
+ dhall-lang/tests/normalization/success/unit/WithB.dhall view
@@ -0,0 +1,1 @@+{ a = 1, b = 2 }
+ dhall-lang/tests/normalization/success/unit/WithChainedA.dhall view
@@ -0,0 +1,4 @@+{-  This test verifies that an implementation correctly handles chained+    `with` expressions+-}+{ a = 1 } with b = 2 with c = 3
+ dhall-lang/tests/normalization/success/unit/WithChainedB.dhall view
@@ -0,0 +1,1 @@+{ a = 1, b = 2, c = 3 }
+ dhall-lang/tests/normalization/success/unit/WithCreateIntermediateRecordsA.dhall view
@@ -0,0 +1,3 @@+{- This test illustrates that if an intermediate record does+   not exist, the `with` operator can create one -}+{ a = 5 } with b.c = 10
+ dhall-lang/tests/normalization/success/unit/WithCreateIntermediateRecordsB.dhall view
@@ -0,0 +1,1 @@+{ a = 5, b.c = 10 }
+ dhall-lang/tests/normalization/success/unit/WithDesugarA.dhall view
@@ -0,0 +1,3 @@+{- This test verifies that an implementation no longer implements the old desugaring (pre-v19.0.0)+-}+\(x: { a : { b : { c : {} } }}) -> x with a.b.c = 42
+ dhall-lang/tests/normalization/success/unit/WithDesugarB.dhall view
@@ -0,0 +1,1 @@+λ(x : { a : { b : { c : {} } } }) → x with a.b.c = 42
+ dhall-lang/tests/normalization/success/unit/WithNestedA.dhall view
@@ -0,0 +1,12 @@+{-  This test verifies that an implementation handles `with` expressions that+    update nested labels correctly++    A common mistake an implementation might make is to produce the following+    result:++        { a.c = 2 }++    ... due to the nested update clobbering the inner record.  A compliant+    implementation extends inner records.+-}+{ a.b = 1 } with a.c = 2
+ dhall-lang/tests/normalization/success/unit/WithNestedB.dhall view
@@ -0,0 +1,1 @@+{ a = { b = 1, c = 2 } }
+ dhall-lang/tests/normalization/success/unit/WithOnOptionalNoneA.dhall view
@@ -0,0 +1,1 @@+(None Natural) with ? = 1
+ dhall-lang/tests/normalization/success/unit/WithOnOptionalNoneB.dhall view
@@ -0,0 +1,1 @@+None Natural
+ dhall-lang/tests/normalization/success/unit/WithOnOptionalSomeA.dhall view
@@ -0,0 +1,1 @@+(Some 0) with ? = 1
+ dhall-lang/tests/normalization/success/unit/WithOnOptionalSomeB.dhall view
@@ -0,0 +1,1 @@+Some 1
+ dhall-lang/tests/normalization/success/unit/WithOptionalDeeplyNestedA.dhall view
@@ -0,0 +1,1 @@+(Some { x = Some { y = Some { z = Some 0 } } }) with ?.x.?.y.?.z.? = 1
+ dhall-lang/tests/normalization/success/unit/WithOptionalDeeplyNestedB.dhall view
@@ -0,0 +1,1 @@+Some { x = Some { y = Some { z = Some 1 } } }
+ dhall-lang/tests/normalization/success/unit/WithOptionalNestedA.dhall view
@@ -0,0 +1,1 @@+{ x = Some 0 } with x.? = 1
+ dhall-lang/tests/normalization/success/unit/WithOptionalNestedB.dhall view
@@ -0,0 +1,1 @@+{ x = Some 1 }
+ dhall-lang/tests/normalization/success/unit/WithPartiallyAbstractA.dhall view
@@ -0,0 +1,4 @@+{- This test verifies that an implementation will evaluate a+partially abstract `with` expression correctly+-}+λ(x : { b : { c : {} } }) → { a = x } with a.b.c = 42
+ dhall-lang/tests/normalization/success/unit/WithPartiallyAbstractB.dhall view
@@ -0,0 +1,1 @@+λ(x : { b : { c : {} } }) → { a = x with b.c = 42 }
+ dhall-lang/tests/normalization/success/unit/WithPriorityA.dhall view
@@ -0,0 +1,6 @@+{-  This test ensures that updates are ordered and latter updates take priority+    when the same field is updated more than one time++    In this example, the `a` field is updated twice, and the latter update wins+-}+{ a = 1 } with a = 2 with a = 3
+ dhall-lang/tests/normalization/success/unit/WithPriorityB.dhall view
@@ -0,0 +1,1 @@+{ a = 3 }
+ dhall-lang/tests/parser/failure/ImportHeadersExteriorHash.dhall view
@@ -0,0 +1,1 @@+(https://example.com/foo using ./headers) sha256:0000000000000000000000000000000000000000000000000000000000000000
+ dhall-lang/tests/parser/failure/ProjectionByTypeNeedsParens.dhall view
@@ -0,0 +1,1 @@+r.{ x: T }
+ dhall-lang/tests/parser/failure/assertBinding.dhall view
@@ -0,0 +1,1 @@+let assert = 2 in 1
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/missingSpace.dhall
@@ -1,2 +0,0 @@--- There needs to be a space between a function and its argument-./example.dhall[1]
+ dhall-lang/tests/parser/failure/nonBase16Hash.dhall view
@@ -0,0 +1,1 @@+./foo sha256:d60d8415e36e86dae7f42933d3b0c4fe3ca238f057fba206c7e9fbf5d784fe1g
+ dhall-lang/tests/parser/failure/nonCharacter.dhall view
@@ -0,0 +1,1 @@+"\u{10FFFF}"
+ dhall-lang/tests/parser/failure/nonCharacterUnbraced.dhall view
@@ -0,0 +1,6 @@+{-+The parser should reject unicode escape sequences for non-characters+(0xNFFFE-0xNFFFF for each `N` in `{ 0 .. F }), regardless of whether they are+braced or not.+-}+"\uFFFE"
+ dhall-lang/tests/parser/failure/nonUtf8.dhall view
@@ -0,0 +1,4 @@+{- This test verifies that an implementation correctly rejects non-UTF8+   characters, such as this one: "í €"+-}+1
+ dhall-lang/tests/parser/failure/spacing/AnnotationNoSpace.dhall view
@@ -0,0 +1,1 @@+x :T
+ dhall-lang/tests/parser/failure/spacing/ApplicationNoSpace1.dhall view
@@ -0,0 +1,1 @@+f(x)
+ dhall-lang/tests/parser/failure/spacing/ApplicationNoSpace2.dhall view
@@ -0,0 +1,2 @@+-- There needs to be a space between a function and its argument+./example.dhall[1]
+ dhall-lang/tests/parser/failure/spacing/AssertNoSpace.dhall view
@@ -0,0 +1,1 @@+assert :T
+ dhall-lang/tests/parser/failure/spacing/ForallNoSpace.dhall view
@@ -0,0 +1,1 @@+forall(x :T) -> x
+ dhall-lang/tests/parser/failure/spacing/HeadersNoSpace.dhall view
@@ -0,0 +1,1 @@+https://example.com/foo using(x)
+ dhall-lang/tests/parser/failure/spacing/IfNoSpace1.dhall view
@@ -0,0 +1,1 @@+if(b) then x else y
+ dhall-lang/tests/parser/failure/spacing/IfNoSpace2.dhall view
@@ -0,0 +1,1 @@+if b then(x) else y
+ dhall-lang/tests/parser/failure/spacing/IfNoSpace3.dhall view
@@ -0,0 +1,1 @@+if b then x else(y)
+ dhall-lang/tests/parser/failure/spacing/ImportAltNoSpace.dhall view
@@ -0,0 +1,1 @@+x ?y
+ dhall-lang/tests/parser/failure/spacing/ImportHashedNoSpace.dhall view
@@ -0,0 +1,1 @@+missingsha256:0000000000000000000000000000000000000000000000000000000000000000
+ dhall-lang/tests/parser/failure/spacing/LambdaNoSpace.dhall view
@@ -0,0 +1,1 @@+\(x :T) -> x
+ dhall-lang/tests/parser/failure/spacing/LetAnnotNoSpace.dhall view
@@ -0,0 +1,1 @@+let x :T = y in e
+ dhall-lang/tests/parser/failure/spacing/LetNoSpace1.dhall view
@@ -0,0 +1,1 @@+letx = y in e
+ dhall-lang/tests/parser/failure/spacing/LetNoSpace2.dhall view
@@ -0,0 +1,1 @@+let x = y in(e)
+ dhall-lang/tests/parser/failure/spacing/LetNoSpace3.dhall view
@@ -0,0 +1,1 @@+let x = NaNin x
+ dhall-lang/tests/parser/failure/spacing/LetNoSpace4.dhall view
@@ -0,0 +1,1 @@+let x = 3let y = x in y
+ dhall-lang/tests/parser/failure/spacing/ListLitEmptyNoSpace.dhall view
@@ -0,0 +1,1 @@+[] :T
+ dhall-lang/tests/parser/failure/spacing/MergeAnnotationNoSpace3.dhall view
@@ -0,0 +1,1 @@+merge x y :T
+ dhall-lang/tests/parser/failure/spacing/MergeNoSpace1.dhall view
@@ -0,0 +1,1 @@+merge(x) y
+ dhall-lang/tests/parser/failure/spacing/MergeNoSpace2.dhall view
@@ -0,0 +1,1 @@+merge x(y)
+ dhall-lang/tests/parser/failure/spacing/NaturalPlusNoSpace.dhall view
@@ -0,0 +1,1 @@+x +y
+ dhall-lang/tests/parser/failure/spacing/RecordTypeNoSpace.dhall view
@@ -0,0 +1,1 @@+{ x :T }
+ dhall-lang/tests/parser/failure/spacing/SomeNoSpace.dhall view
@@ -0,0 +1,1 @@+Some(x)
+ dhall-lang/tests/parser/failure/spacing/ToMapAnnotNoSpace.dhall view
@@ -0,0 +1,1 @@+toMap x :T
+ dhall-lang/tests/parser/failure/spacing/ToMapNoSpace.dhall view
@@ -0,0 +1,1 @@+toMap(x)
+ dhall-lang/tests/parser/failure/spacing/UnionTypeNoSpace.dhall view
@@ -0,0 +1,1 @@+< x :T >
+ dhall-lang/tests/parser/failure/surrogatePairUnbraced.dhall view
@@ -0,0 +1,5 @@+{-+The parser should reject unicode escape sequences for surrogate pairs+(0xD800-DFFF), regardless of whether they are braced or not.+-}+"\uD800"
+ dhall-lang/tests/parser/failure/time/DateTimeZone.dhall view
@@ -0,0 +1,2 @@+-- A date and time zone is not valid (because the time is missing)+2011-04-01+02:00
+ dhall-lang/tests/parser/failure/time/InvalidDayOfMonth.dhall view
@@ -0,0 +1,2 @@+-- April only has 30 days+2000-04-31
+ dhall-lang/tests/parser/failure/time/InvalidHour.dhall view
@@ -0,0 +1,2 @@+-- Hours must range between 0-23+24:00:00
+ dhall-lang/tests/parser/failure/time/InvalidLeapSecond.dhall view
@@ -0,0 +1,3 @@+-- Leap seconds are not permitted by the Dhall standard, even though RFC 3339+-- supports them+2016-12-31T23:59:60
+ dhall-lang/tests/parser/failure/time/InvalidMinute.dhall view
@@ -0,0 +1,2 @@+-- Minutes must range between 0-59+00:60:00
+ dhall-lang/tests/parser/failure/time/InvalidMonth.dhall view
@@ -0,0 +1,2 @@+-- Months must be between 1-12+2000-13-01
+ dhall-lang/tests/parser/failure/time/InvalidSecond.dhall view
@@ -0,0 +1,2 @@+-- Seconds must range between 0-59 (and leap seconds are not supported)+00:00:60
+ dhall-lang/tests/parser/failure/time/NegativeYear.dhall view
@@ -0,0 +1,2 @@+-- Negative years are not permitted+-0001-01-01
+ dhall-lang/tests/parser/failure/time/YearTooLarge.dhall view
@@ -0,0 +1,2 @@+-- Only 4-digit years are permitted+10000-01-01
+ dhall-lang/tests/parser/failure/unit/AssertNoAnnotation.dhall view
@@ -0,0 +1,1 @@+assert
+ dhall-lang/tests/parser/failure/unit/BoolLitTrueWithIndex.dhall view
@@ -0,0 +1,1 @@+True@0
+ dhall-lang/tests/parser/failure/unit/BuiltinBoolWithIndex.dhall view
@@ -0,0 +1,1 @@+Bool@1
+ dhall-lang/tests/parser/failure/unit/BuiltinTypeWithIndex.dhall view
@@ -0,0 +1,1 @@+Type@0
+ dhall-lang/tests/parser/failure/unit/ImportEnvWrongEscape.dhall view
@@ -0,0 +1,1 @@+env:"\$"
+ dhall-lang/tests/parser/failure/unit/ListLitEmptyAnnotation.dhall view
@@ -0,0 +1,1 @@+([]) : List T
+ dhall-lang/tests/parser/failure/unit/ListLitEmptyMissingAnnotation.dhall view
@@ -0,0 +1,1 @@+[]
+ dhall-lang/tests/parser/failure/unit/ListLitTwoCommas.dhall view
@@ -0,0 +1,1 @@+[ ,, ]
+ dhall-lang/tests/parser/failure/unit/MergeAlone.dhall view
@@ -0,0 +1,1 @@+merge
+ dhall-lang/tests/parser/failure/unit/MergeOneArgument.dhall view
@@ -0,0 +1,1 @@+merge x
+ dhall-lang/tests/parser/failure/unit/NaturalLitLeadingZero.dhall view
@@ -0,0 +1,1 @@+042
+ dhall-lang/tests/parser/failure/unit/OldUnionLitSyntax.dhall view
@@ -0,0 +1,1 @@+< x = 3 | y : Bool >
+ dhall-lang/tests/parser/failure/unit/ProjectionTwoCommas.dhall view
@@ -0,0 +1,1 @@+foo.{ ,, }
+ dhall-lang/tests/parser/failure/unit/RecordFieldMustNotBeKeyword00.dhall view
@@ -0,0 +1,1 @@+{ if: Text }
+ dhall-lang/tests/parser/failure/unit/RecordFieldMustNotBeKeyword01.dhall view
@@ -0,0 +1,1 @@+{ then: Text }
+ dhall-lang/tests/parser/failure/unit/RecordFieldMustNotBeKeyword02.dhall view
@@ -0,0 +1,1 @@+{ else: Text }
+ dhall-lang/tests/parser/failure/unit/RecordFieldMustNotBeKeyword03.dhall view
@@ -0,0 +1,1 @@+{ let: Text }
+ dhall-lang/tests/parser/failure/unit/RecordFieldMustNotBeKeyword04.dhall view
@@ -0,0 +1,1 @@+{ in: Text }
+ dhall-lang/tests/parser/failure/unit/RecordFieldMustNotBeKeyword05.dhall view
@@ -0,0 +1,1 @@+{ using: Text }
+ dhall-lang/tests/parser/failure/unit/RecordFieldMustNotBeKeyword06.dhall view
@@ -0,0 +1,1 @@+{ missing: Text }
+ dhall-lang/tests/parser/failure/unit/RecordFieldMustNotBeKeyword07.dhall view
@@ -0,0 +1,1 @@+{ assert: Text }
+ dhall-lang/tests/parser/failure/unit/RecordFieldMustNotBeKeyword08.dhall view
@@ -0,0 +1,1 @@+{ as: Text }
+ dhall-lang/tests/parser/failure/unit/RecordFieldMustNotBeKeyword09.dhall view
@@ -0,0 +1,1 @@+{ Infinity: Text }
+ dhall-lang/tests/parser/failure/unit/RecordFieldMustNotBeKeyword10.dhall view
@@ -0,0 +1,1 @@+{ NaN: Text }
+ dhall-lang/tests/parser/failure/unit/RecordFieldMustNotBeKeyword11.dhall view
@@ -0,0 +1,1 @@+{ merge: Text }
+ dhall-lang/tests/parser/failure/unit/RecordFieldMustNotBeKeyword12.dhall view
@@ -0,0 +1,1 @@+{ toMap: Text }
+ dhall-lang/tests/parser/failure/unit/RecordFieldMustNotBeKeyword13.dhall view
@@ -0,0 +1,1 @@+{ with: Text }
+ dhall-lang/tests/parser/failure/unit/RecordFieldMustNotBeKeyword14.dhall view
@@ -0,0 +1,1 @@+{ forall: Text }
+ dhall-lang/tests/parser/failure/unit/RecordLitPunDotted.dhall view
@@ -0,0 +1,1 @@+{ x.y.z }
+ dhall-lang/tests/parser/failure/unit/RecordTwoCommas.dhall view
@@ -0,0 +1,1 @@+{ ,, }
+ dhall-lang/tests/parser/failure/unit/SomeAlone.dhall view
@@ -0,0 +1,1 @@+Some
+ dhall-lang/tests/parser/failure/unit/UnionTypeTwoDelims.dhall view
@@ -0,0 +1,1 @@+< || >
+ dhall-lang/tests/parser/failure/unit/UrlWithQuotedPath.dhall view
@@ -0,0 +1,1 @@+https://example.com/"a%20b"/c
+ dhall-lang/tests/parser/failure/unit/UsingToMap.dhall view
@@ -0,0 +1,8 @@+{-  At one point the Haskell implementation permitted this idiom, which was not+    standards-compliant++    The problem with the following expression is that the argument to `using`+    is parsed as a `completionExpression`, which means that any use of `toMap`+    within a `using` clause must be parenthesized+-}+https://example.com using toMap { Foo = "Bar" }
+ dhall-lang/tests/parser/failure/unit/WithPrecedence1.dhall view
@@ -0,0 +1,1 @@+{ x = 0 } // { y = 1 } with x = 1
+ dhall-lang/tests/parser/failure/unit/WithPrecedence2.dhall view
@@ -0,0 +1,1 @@+foo { x = 0 } with x = 1
+ dhall-lang/tests/parser/failure/unit/WithPrecedence3.dhall view
@@ -0,0 +1,1 @@+{ x = 0 } with x = 1 : T
+ dhall-lang/tests/parser/failure/unit/WithWhitespace.dhall view
@@ -0,0 +1,2 @@+-- For https://github.com/dhall-lang/dhall-haskell/issues/2212+{=}with foo = 0with bar = 1
+ dhall-lang/tests/parser/failure/unit/showConstructorAlone.dhall view
@@ -0,0 +1,1 @@+showConstructor
− dhall-lang/tests/parser/failure/urlWithoutPath.dhall
@@ -1,2 +0,0 @@--- See issue #205 for why this is not permitted-http://example.com/
− dhall-lang/tests/parser/success/RecordProjectionByType.dhall
@@ -1,15 +0,0 @@-let example1 = λ(A : Type) → λ(B : Type) → λ(C : { x : A, y : B }) → C.({ x : A }) : { x : A }--let example2 =-	  λ(A : Type)-	→ λ(B : Type)-	→ λ(C : { p : A, q : B })-	→ C.(let r = { p : A } in r) : { p : A }--let A = Natural--let B = Text--in--(example1 A B { x = 10, y = "Text" }) ∧ (example2 A B { p = 10, q = "Text" }) : { x : A, p : A }
dhall-lang/tests/parser/success/annotationsA.dhall view
@@ -1,4 +1,1 @@-{ foo = ([] : List Natural) # [1, 2, 3] # ([1, 2, 3] : List Natural)-, bar = [] : Optional Natural-, baz = [1] : Optional Natural-} : { foo : List Natural, bar : Optional Natural, baz : Optional Natural }+([] : List Natural) # [ 1, 2, 3 ] # ([ 1, 2, 3 ] : List Natural) : List Natural
dhall-lang/tests/parser/success/annotationsB.dhallb view

binary file changed (167 → 76 bytes)

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

binary file changed (absent → 83 bytes)

dhall-lang/tests/parser/success/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/doubleA.dhall
@@ -1,1 +0,0 @@-[ 1.1, -1.1, 1e1, 1.1e1, NaN, Infinity, -Infinity, 0.0 ]
− dhall-lang/tests/parser/success/doubleB.dhallb

binary file changed (43 → absent bytes)

+ dhall-lang/tests/parser/success/hexadecimalA.dhall view
@@ -0,0 +1,6 @@+  λ(x : Bool)+→ λ(x : Bool)+→ { example0 = 0xFF+  , example1 = -0x1A10+  , example2 = x@0x01+  }
+ dhall-lang/tests/parser/success/hexadecimalB.dhallb view
@@ -0,0 +1,1 @@+„axdBool„axdBool‚£hexample0‚ÿhexample1‚9hexample2‚ax
− dhall-lang/tests/parser/success/ifThenElseA.dhall
@@ -1,1 +0,0 @@-if True then 1 else 2
− dhall-lang/tests/parser/success/ifThenElseB.dhallb
@@ -1,1 +0,0 @@-„õ‚‚
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/leadingSeparatorsA.dhall view
@@ -0,0 +1,10 @@+{ emptyRecordLiteral = { , = }+, emptyRecordType = { , }+, emptyList = [,] : List Natural+, emptyUnionType = < | >++, recordLiteral = { , x = 1, y = True }+, recordType = { , x : Natural, y : Bool }+, list = [ , 1, 2 ]+, unionType = < | x : Natural | y : Bool >+}
+ dhall-lang/tests/parser/success/leadingSeparatorsB.dhallb view
@@ -0,0 +1,1 @@+‚¨iemptyList‚gNaturalremptyRecordLiteral‚ oemptyRecordType‚ nemptyUnionType‚ dlist„ö‚‚mrecordLiteral‚¢ax‚ayõjrecordType‚¢axgNaturalaydBooliunionType‚¢axgNaturalaydBool
− dhall-lang/tests/parser/success/letA.dhall
@@ -1,3 +0,0 @@-    let x = 1-in  let y : Natural = 2-in  x
− dhall-lang/tests/parser/success/letB.dhallb

binary file changed (29 → absent bytes)

+ dhall-lang/tests/parser/success/lineCommentCRLFA.dhall view
@@ -0,0 +1,3 @@+-- foo
+
+1
+ dhall-lang/tests/parser/success/lineCommentCRLFB.dhallb view
@@ -0,0 +1,1 @@
+ dhall-lang/tests/parser/success/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/missingFooA.dhall view
@@ -0,0 +1,1 @@+missingFoo
+ dhall-lang/tests/parser/success/missingFooB.dhallb view

binary file changed (absent → 13 bytes)

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

binary file changed (absent → 6 bytes)

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

binary file changed (absent → 11 bytes)

+ dhall-lang/tests/parser/success/mixedBlockLineCommentA.dhall view
@@ -0,0 +1,6 @@+{- foo -}+-- bar+{- --baz -}+-- {- qux -}++1
+ dhall-lang/tests/parser/success/mixedBlockLineCommentB.dhallb view
@@ -0,0 +1,1 @@
− dhall-lang/tests/parser/success/multiletA.dhall
@@ -1,3 +0,0 @@-let a = 1-let b = 2-in  a + b
− dhall-lang/tests/parser/success/multiletB.dhallb

binary file changed (26 → absent bytes)

dhall-lang/tests/parser/success/naturalA.dhall view
@@ -1,1 +1,1 @@-[ 0, 1, 01, 10 ]+[ 0, 1, 10 ]
dhall-lang/tests/parser/success/naturalB.dhallb view

binary file changed (15 → 12 bytes)

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

binary file changed (absent → 15 bytes)

dhall-lang/tests/parser/success/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/recordProjectionByExpressionA.dhall view
@@ -0,0 +1,15 @@+let example1 = λ(A : Type) → λ(B : Type) → λ(C : { x : A, y : B }) → C.({ x : A }) : { x : A }++let example2 =+	  λ(A : Type)+	→ λ(B : Type)+	→ λ(C : { p : A, q : B })+	→ C.(let r = { p : A } in r) : { p : A }++let A = Natural++let B = Text++in++(example1 A B { x = 10, y = "Text" }) ∧ (example2 A B { p = 10, q = "Text" }) : { x : A, p : A }
+ dhall-lang/tests/parser/success/recordProjectionByExpressionB.dhallb view

binary file changed (absent → 279 bytes)

+ dhall-lang/tests/parser/success/text/dollarSignA.dhall view
@@ -0,0 +1,1 @@+"$"
+ dhall-lang/tests/parser/success/text/dollarSignB.dhallb view
@@ -0,0 +1,1 @@+‚a$
dhall-lang/tests/parser/success/text/escapedDoubleQuotedStringA.dhall view
@@ -1,1 +1,1 @@-"\\\"\$\\\/\b\f\n\r\t \u2200(a : Type) \u2192 a"+"\\\"\$\\\/\b\f\n\r\t\u{1D11E} \u2200(a : Type) \u2192 a"
dhall-lang/tests/parser/success/text/escapedDoubleQuotedStringB.dhallb view
@@ -1,2 +1,2 @@-‚x\"$\/-
	 ∀(a : Type) → a+‚x"\"$\/+
	𝄞 ∀(a : Type) → a
+ 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/nonAssignedUnicodeA.dhall view
@@ -0,0 +1,1 @@+"\u{1FFF0}"
+ dhall-lang/tests/parser/success/text/nonAssignedUnicodeB.dhallb view
@@ -0,0 +1,1 @@+‚d🿰
dhall-lang/tests/parser/success/text/preserveCommentA.dhall view
@@ -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/singleQuoteConcatA.dhall view
@@ -0,0 +1,5 @@+''+a''++++''+b''
+ dhall-lang/tests/parser/success/text/singleQuoteConcatB.dhallb view
@@ -0,0 +1,1 @@+„‚aa‚ab
+ dhall-lang/tests/parser/success/text/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/toMapA.dhall view
@@ -0,0 +1,1 @@+toMap { foo= 1, bar= 4, baz= 9 }
+ dhall-lang/tests/parser/success/toMapB.dhallb view
@@ -0,0 +1,1 @@+‚‚£cbar‚cbaz‚	cfoo‚
− dhall-lang/tests/parser/success/unionA.dhall
@@ -1,4 +0,0 @@-< A : {   }-| B = { = }-| C : {}-> : < A : {} | B : {} | C : {} >
− dhall-lang/tests/parser/success/unionB.dhallb
@@ -1,1 +0,0 @@-ƒ„aB‚ ¢aA‚ aC‚ ‚£aA‚ aB‚ aC‚ 
+ dhall-lang/tests/parser/success/unit/AnnotationA.dhall view
@@ -0,0 +1,1 @@+x : T
+ dhall-lang/tests/parser/success/unit/AnnotationB.dhallb view

binary file changed (absent → 11 bytes)

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

binary file changed (absent → 6 bytes)

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

binary file changed (absent → 13 bytes)

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

binary file changed (absent → 13 bytes)

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

binary file changed (absent → 12 bytes)

+ dhall-lang/tests/parser/success/unit/BuiltinListBuildA.dhall view
@@ -0,0 +1,1 @@+List/Build
+ dhall-lang/tests/parser/success/unit/BuiltinListBuildB.dhallb view

binary file changed (absent → 13 bytes)

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

binary file changed (absent → 11 bytes)

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

binary file changed (absent → 11 bytes)

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

binary file changed (absent → 5 bytes)

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

binary file changed (absent → 9 bytes)

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

binary file changed (absent → 5 bytes)

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

binary file changed (absent → 3 bytes)

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

binary file changed (absent → 3 bytes)

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

binary file changed (absent → 3 bytes)

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

binary file changed (absent → 3 bytes)

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

binary file changed (absent → 3 bytes)

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

binary file changed (absent → 3 bytes)

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

binary file changed (absent → 8 bytes)

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

binary file changed (absent → 11 bytes)

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

binary file changed (absent → 8 bytes)

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

binary file changed (absent → 12 bytes)

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

binary file changed (absent → 18 bytes)

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

binary file changed (absent → 10 bytes)

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

binary file changed (absent → 10 bytes)

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

binary file changed (absent → 12 bytes)

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

binary file changed (absent → 20 bytes)

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

binary file changed (absent → 10 bytes)

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

binary file changed (absent → 12 bytes)

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

binary file changed (absent → 12 bytes)

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

binary file changed (absent → 17 bytes)

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

binary file changed (absent → 17 bytes)

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

binary file changed (absent → 27 bytes)

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

binary file changed (absent → 27 bytes)

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

binary file changed (absent → 14 bytes)

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

binary file changed (absent → 6 bytes)

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

binary file changed (absent → 7 bytes)

− dhall-lang/tests/parser/success/unit/ListLitEmptyA.dhall
@@ -1,1 +0,0 @@-[] : List T
− dhall-lang/tests/parser/success/unit/ListLitEmptyB.dhallb

binary file changed (6 → absent bytes)

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

binary file changed (absent → 18 bytes)

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

binary file changed (absent → 11 bytes)

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

binary file changed (absent → 25 bytes)

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

binary file changed (absent → 11 bytes)

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

binary file changed (absent → 11 bytes)

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

binary file changed (absent → 11 bytes)

+ dhall-lang/tests/parser/success/unit/ListWithNewlineA.dhall view
@@ -0,0 +1,11 @@+[ [+    1,+    2,+    3,+  ]+, [+  , 1+  , 2+  , 3+  ]+]
+ dhall-lang/tests/parser/success/unit/ListWithNewlineB.dhallb view
@@ -0,0 +1,1 @@+„ö…ö‚‚‚…ö‚‚‚
+ dhall-lang/tests/parser/success/unit/ProjectionA.dhall view
@@ -0,0 +1,1 @@+r.{x, y, z}
+ dhall-lang/tests/parser/success/unit/ProjectionB.dhallb view

binary file changed (absent → 12 bytes)

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

binary file changed (absent → 12 bytes)

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

binary file changed (absent → 12 bytes)

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

binary file changed (absent → 12 bytes)

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

binary file changed (absent → 13 bytes)

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

binary file changed (absent → 21 bytes)

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

binary file changed (absent → 22 bytes)

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

binary file changed (absent → 35 bytes)

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

binary file changed (absent → 15 bytes)

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

binary file changed (absent → 11 bytes)

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

binary file changed (absent → 13 bytes)

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

binary file changed (absent → 13 bytes)

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

binary file changed (absent → 15 bytes)

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

binary file changed (absent → 15 bytes)

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

binary file changed (absent → 15 bytes)

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

binary file changed (absent → 15 bytes)

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

binary file changed (absent → 16 bytes)

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

binary file changed (absent → 20 bytes)

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

binary file changed (absent → 9 bytes)

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

binary file changed (absent → 6 bytes)

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

binary file changed (absent → 11 bytes)

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

binary file changed (absent → 7 bytes)

+ dhall-lang/tests/parser/success/unit/TrailingLineCommentWithoutNewlineA.dhall view
@@ -0,0 +1,2 @@+-- This test verifies that a trailing line comment does not require a newline+1--
+ dhall-lang/tests/parser/success/unit/TrailingLineCommentWithoutNewlineB.dhallb view
@@ -0,0 +1,1 @@
− dhall-lang/tests/parser/success/unit/UnionLit1A.dhall
@@ -1,1 +0,0 @@-< x = t | y: T | z | w: T >
− dhall-lang/tests/parser/success/unit/UnionLit1B.dhallb

binary file changed (24 → absent bytes)

− dhall-lang/tests/parser/success/unit/UnionLit2A.dhall
@@ -1,1 +0,0 @@-< x: T | y = t | z | w: T >
− dhall-lang/tests/parser/success/unit/UnionLit2B.dhallb

binary file changed (24 → absent bytes)

+ dhall-lang/tests/parser/success/unit/UnionTypeEmptyDelimA.dhall view
@@ -0,0 +1,1 @@+< | >
+ dhall-lang/tests/parser/success/unit/UnionTypeEmptyDelimB.dhallb view
@@ -0,0 +1,1 @@+‚ 
+ dhall-lang/tests/parser/success/unit/UnionTypeLeadingDelimA.dhall view
@@ -0,0 +1,1 @@+< | x: T | y: U >
+ dhall-lang/tests/parser/success/unit/UnionTypeLeadingDelimB.dhallb view

binary file changed (absent → 15 bytes)

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

binary file changed (absent → 15 bytes)

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

binary file changed (absent → 15 bytes)

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

binary file changed (absent → 6 bytes)

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

binary file changed (absent → 23 bytes)

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

binary file changed (absent → 26 bytes)

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

binary file changed (absent → 23 bytes)

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

binary file changed (absent → 53 bytes)

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

binary file changed (absent → 27 bytes)

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

binary file changed (absent → 107 bytes)

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

binary file changed (absent → 107 bytes)

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

binary file changed (absent → 72 bytes)

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

binary file changed (absent → 72 bytes)

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

binary file changed (absent → 24 bytes)

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

binary file changed (absent → 6 bytes)

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

binary file changed (16 → 20 bytes)

dhall-lang/tests/parser/success/unit/import/inlineUsingA.dhall view
@@ -8,7 +8,7 @@ -}  https://example.com/foo using-    [ { header = "Authorization"-      , value  = "token 5199831f4dd3b79e7c5b7e0ebe75d67aa66e79d4"+    [ { mapKey   = "Authorization"+      , mapValue = "token 5199831f4dd3b79e7c5b7e0ebe75d67aa66e79d4"       }     ]
dhall-lang/tests/parser/success/unit/import/inlineUsingB.dhallb view

binary file changed (108 → 111 bytes)

− dhall-lang/tests/parser/success/unit/import/parenthesizeUsingA.dhall
@@ -1,1 +0,0 @@-https://raw.githubusercontent.com/dhall-lang/Prelude/c79c2bc3c46f129cc5b6d594ce298a381bcae92c/List/replicate using (./a.dhall sha256:16173e984d35ee3ffd8b6b79167df89480e67d1cd03ea5d0fc93689e4d928e61) sha256:b0e3ec1797b32c80c0bcb7e8254b08c7e9e35e75e6b410c7ac21477ab90167ad
− dhall-lang/tests/parser/success/unit/import/parenthesizeUsingB.dhallb

binary file changed (241 → absent bytes)

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

binary file changed (47 → 47 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 (78 → 22 bytes)

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

binary file changed (absent → 35 bytes)

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

binary file changed (absent → 116 bytes)

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

binary file changed (absent → 21 bytes)

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

binary file changed (absent → 21 bytes)

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

binary file changed (absent → 29 bytes)

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

binary file changed (absent → 24 bytes)

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

binary file changed (absent → 42 bytes)

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

binary file changed (absent → 41 bytes)

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

binary file changed (absent → 33 bytes)

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

binary file changed (absent → 30 bytes)

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

binary file changed (absent → 36 bytes)

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

binary file changed (absent → 58 bytes)

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

binary file changed (absent → 55 bytes)

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

binary file changed (absent → 25 bytes)

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

binary file changed (absent → 63 bytes)

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

binary file changed (absent → 59 bytes)

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

binary file changed (absent → 29 bytes)

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

binary file changed (absent → 75 bytes)

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

binary file changed (absent → 33 bytes)

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

binary file changed (absent → 25 bytes)

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

binary file changed (absent → 11 bytes)

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

binary file changed (absent → 25 bytes)

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

binary file changed (absent → 11 bytes)

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

binary file changed (absent → 25 bytes)

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

binary file changed (absent → 11 bytes)

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

binary file changed (absent → 25 bytes)

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

binary file changed (absent → 11 bytes)

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

binary file changed (absent → 25 bytes)

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

binary file changed (absent → 11 bytes)

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

binary file changed (absent → 25 bytes)

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

binary file changed (absent → 11 bytes)

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

binary file changed (absent → 25 bytes)

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

binary file changed (absent → 11 bytes)

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

binary file changed (absent → 25 bytes)

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

binary file changed (absent → 11 bytes)

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

binary file changed (absent → 25 bytes)

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

binary file changed (absent → 11 bytes)

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

binary file changed (absent → 59 bytes)

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

binary file changed (absent → 45 bytes)

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

binary file changed (absent → 42 bytes)

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

binary file changed (absent → 25 bytes)

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

binary file changed (absent → 11 bytes)

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

binary file changed (absent → 25 bytes)

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

binary file changed (absent → 11 bytes)

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

binary file changed (absent → 25 bytes)

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

binary file changed (absent → 11 bytes)

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

binary file changed (absent → 25 bytes)

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

binary file changed (absent → 11 bytes)

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

binary file changed (absent → 25 bytes)

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

binary file changed (absent → 11 bytes)

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

binary file changed (absent → 25 bytes)

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

binary file changed (absent → 11 bytes)

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

binary file changed (absent → 25 bytes)

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

binary file changed (absent → 11 bytes)

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

binary file changed (absent → 36 bytes)

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

binary file changed (absent → 14 bytes)

+ dhall-lang/tests/semantic-hash/success/haskell-tutorial/access/0A.dhall view
@@ -0,0 +1,1 @@+{ x = "foo" }.x
+ dhall-lang/tests/semantic-hash/success/haskell-tutorial/access/0B.hash view
@@ -0,0 +1,1 @@+sha256:fd881e3d48cbc85b4044697bdce8167a77f3fb4665ff0b647a1210a17528818a
+ dhall-lang/tests/semantic-hash/success/haskell-tutorial/access/1A.dhall view
@@ -0,0 +1,1 @@+< Foo : Text | Bar : Natural >.Foo
+ dhall-lang/tests/semantic-hash/success/haskell-tutorial/access/1B.hash view
@@ -0,0 +1,1 @@+sha256:35ba8bddad36acfb29cc6f1700364544c145e96cf522f592f18f90c2f96e6e9c
+ dhall-lang/tests/semantic-hash/success/haskell-tutorial/combineTypes/0A.dhall view
@@ -0,0 +1,1 @@+{ foo : { bar : Text } } ⩓ { foo : { baz : Bool }, qux : Integer }
+ dhall-lang/tests/semantic-hash/success/haskell-tutorial/combineTypes/0B.hash view
@@ -0,0 +1,1 @@+sha256:4495bbf3fea6c579c65ee51463b225747803b94668013528b9ca0384304cb350
+ dhall-lang/tests/semantic-hash/success/haskell-tutorial/combineTypes/1A.dhall view
@@ -0,0 +1,1 @@+{ foo : { bar : Text } } //\\ { foo : { baz : Bool }, qux : Integer }
+ dhall-lang/tests/semantic-hash/success/haskell-tutorial/combineTypes/1B.hash view
@@ -0,0 +1,1 @@+sha256:4495bbf3fea6c579c65ee51463b225747803b94668013528b9ca0384304cb350
+ dhall-lang/tests/semantic-hash/success/haskell-tutorial/prefer/0A.dhall view
@@ -0,0 +1,1 @@+{ foo = 1, bar = "ABC" } // { baz = True }
+ dhall-lang/tests/semantic-hash/success/haskell-tutorial/prefer/0B.hash view
@@ -0,0 +1,1 @@+sha256:18fbad84131d28b6d412e6bc09d5ee8eaf432b639c6cc6f1bef1b4ef366642d7
+ dhall-lang/tests/semantic-hash/success/haskell-tutorial/projection/0A.dhall view
@@ -0,0 +1,1 @@+{ x = 1, y = True, z = "ABC" }.{ x, y }
+ dhall-lang/tests/semantic-hash/success/haskell-tutorial/projection/0B.hash view
@@ -0,0 +1,1 @@+sha256:b7ae500723633be94b53b905384236fcd18cbce59314bb51044bb7d3f3939e6e
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/and/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/and.dhall [ True, False, True ]
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/and/0B.hash view
@@ -0,0 +1,1 @@+sha256:2017ff3461395672aa0aa4f64894fd2f95a4b120e2690e8951656d79adc2eed2
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/and/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/and.dhall ([] : List Bool)
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/and/1B.hash view
@@ -0,0 +1,1 @@+sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/build/0A.dhall view
@@ -0,0 +1,2 @@+../../../../../../Prelude/Bool/build.dhall+(λ(bool : Type) → λ(true : bool) → λ(false : bool) → true)
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/build/0B.hash view
@@ -0,0 +1,1 @@+sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/build/1A.dhall view
@@ -0,0 +1,2 @@+../../../../../../Prelude/Bool/build.dhall+(λ(bool : Type) → λ(true : bool) → λ(false : bool) → false)
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/build/1B.hash view
@@ -0,0 +1,1 @@+sha256:2017ff3461395672aa0aa4f64894fd2f95a4b120e2690e8951656d79adc2eed2
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/even/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/even.dhall [ False, True, False ]
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/even/0B.hash view
@@ -0,0 +1,1 @@+sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/even/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/even.dhall [ False, True ]
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/even/1B.hash view
@@ -0,0 +1,1 @@+sha256:2017ff3461395672aa0aa4f64894fd2f95a4b120e2690e8951656d79adc2eed2
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/even/2A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/even.dhall [ False ]
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/even/2B.hash view
@@ -0,0 +1,1 @@+sha256:2017ff3461395672aa0aa4f64894fd2f95a4b120e2690e8951656d79adc2eed2
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/even/3A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/even.dhall ([] : List Bool)
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/even/3B.hash view
@@ -0,0 +1,1 @@+sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/fold/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/fold.dhall True Natural 0 1
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/fold/0B.hash view
@@ -0,0 +1,1 @@+sha256:d0a48d41dcc572839faa9499b6c316b8d0d7115efac2ac770f062cd5fd6d0181
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/fold/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/fold.dhall False Natural 0 1
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/fold/1B.hash view
@@ -0,0 +1,1 @@+sha256:d60d8415e36e86dae7f42933d3b0c4fe3ca238f057fba206c7e9fbf5d784fe15
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/not/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/not.dhall True
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/not/0B.hash view
@@ -0,0 +1,1 @@+sha256:2017ff3461395672aa0aa4f64894fd2f95a4b120e2690e8951656d79adc2eed2
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/not/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/not.dhall False
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/not/1B.hash view
@@ -0,0 +1,1 @@+sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/odd/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/odd.dhall [ True, False, True ]
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/odd/0B.hash view
@@ -0,0 +1,1 @@+sha256:2017ff3461395672aa0aa4f64894fd2f95a4b120e2690e8951656d79adc2eed2
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/odd/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/odd.dhall [ True, False ]
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/odd/1B.hash view
@@ -0,0 +1,1 @@+sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/odd/2A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/odd.dhall [ True ]
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/odd/2B.hash view
@@ -0,0 +1,1 @@+sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/odd/3A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/odd.dhall ([] : List Bool)
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/odd/3B.hash view
@@ -0,0 +1,1 @@+sha256:2017ff3461395672aa0aa4f64894fd2f95a4b120e2690e8951656d79adc2eed2
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/or/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/or.dhall [ True, False, True ]
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/or/0B.hash view
@@ -0,0 +1,1 @@+sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/or/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/or.dhall ([] : List Bool)
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/or/1B.hash view
@@ -0,0 +1,1 @@+sha256:2017ff3461395672aa0aa4f64894fd2f95a4b120e2690e8951656d79adc2eed2
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/show/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/show.dhall True
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/show/0B.hash view
@@ -0,0 +1,1 @@+sha256:cdbb7fd982ba05e709fe67b23818fffb65ff9c0b8abde1abb5ac1a8245891a3f
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/show/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/show.dhall False
+ dhall-lang/tests/semantic-hash/success/prelude/Bool/show/1B.hash view
@@ -0,0 +1,1 @@+sha256:2357bb42b56beb99180d967177c0490061bd3536a147dfe144d2630f983004e5
+ dhall-lang/tests/semantic-hash/success/prelude/Double/show/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Double/show.dhall -3.1
+ dhall-lang/tests/semantic-hash/success/prelude/Double/show/0B.hash view
@@ -0,0 +1,1 @@+sha256:d0b3cdb4f3cd5375495629450de676f445c0da6980a5ada251df199079d0ef89
+ dhall-lang/tests/semantic-hash/success/prelude/Double/show/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Double/show.dhall 0.4
+ dhall-lang/tests/semantic-hash/success/prelude/Double/show/1B.hash view
@@ -0,0 +1,1 @@+sha256:dd5e8756d06f12ef6e003dc769b6e1222e5aa0c8491579dc65b2dd6f4f0ec53d
+ dhall-lang/tests/semantic-hash/success/prelude/Integer/show/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Integer/show.dhall -3
+ dhall-lang/tests/semantic-hash/success/prelude/Integer/show/0B.hash view
@@ -0,0 +1,1 @@+sha256:053de6c2b7f281dd82dd9b643cc848e64633b88c9c57082ec0ac41257c5592d7
+ dhall-lang/tests/semantic-hash/success/prelude/Integer/show/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Integer/show.dhall +0
+ dhall-lang/tests/semantic-hash/success/prelude/Integer/show/1B.hash view
@@ -0,0 +1,1 @@+sha256:4ab1c5aa262f39cdbe1f4924accb69bb44e2a616b5a0ca39655eebd0cc863d33
+ dhall-lang/tests/semantic-hash/success/prelude/Integer/toDouble/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Integer/toDouble.dhall -3
+ dhall-lang/tests/semantic-hash/success/prelude/Integer/toDouble/0B.hash view
@@ -0,0 +1,1 @@+sha256:3c97d2d6c7d01c1c324e6e0a7fcf3b756ff56cf1bf398c4945f04898ae9325a7
+ dhall-lang/tests/semantic-hash/success/prelude/Integer/toDouble/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Integer/toDouble.dhall +2
+ dhall-lang/tests/semantic-hash/success/prelude/Integer/toDouble/1B.hash view
@@ -0,0 +1,1 @@+sha256:fe5c1f8c6cc72fc9aeb61e3b0c5217bf62d2427bcfa678aeefeaa9d04cb9627c
+ dhall-lang/tests/semantic-hash/success/prelude/List/all/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/all.dhall Natural Natural/even [ 2, 3, 5 ]
+ dhall-lang/tests/semantic-hash/success/prelude/List/all/0B.hash view
@@ -0,0 +1,1 @@+sha256:2017ff3461395672aa0aa4f64894fd2f95a4b120e2690e8951656d79adc2eed2
+ dhall-lang/tests/semantic-hash/success/prelude/List/all/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/all.dhall Natural Natural/even ([] : List Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/List/all/1B.hash view
@@ -0,0 +1,1 @@+sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ dhall-lang/tests/semantic-hash/success/prelude/List/any/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/any.dhall Natural Natural/even [ 2, 3, 5 ]
+ dhall-lang/tests/semantic-hash/success/prelude/List/any/0B.hash view
@@ -0,0 +1,1 @@+sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ dhall-lang/tests/semantic-hash/success/prelude/List/any/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/any.dhall Natural Natural/even ([] : List Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/List/any/1B.hash view
@@ -0,0 +1,1 @@+sha256:2017ff3461395672aa0aa4f64894fd2f95a4b120e2690e8951656d79adc2eed2
+ dhall-lang/tests/semantic-hash/success/prelude/List/build/0A.dhall view
@@ -0,0 +1,7 @@+../../../../../../Prelude/List/build.dhall+Text+( λ(list : Type)+→ λ(cons : Text → list → list)+→ λ(nil : list)+→ cons "ABC" (cons "DEF" nil)+)
+ dhall-lang/tests/semantic-hash/success/prelude/List/build/0B.hash view
@@ -0,0 +1,1 @@+sha256:8a08646db7447b14cf03a497635242b6fb76365017fc1699b2a8807272a2ec58
+ dhall-lang/tests/semantic-hash/success/prelude/List/build/1A.dhall view
@@ -0,0 +1,7 @@+../../../../../../Prelude/List/build.dhall+Text+( λ(list : Type)+→ λ(cons : Text → list → list)+→ λ(nil : list)+→ nil+)
+ dhall-lang/tests/semantic-hash/success/prelude/List/build/1B.hash view
@@ -0,0 +1,1 @@+sha256:6da0c98142d1168ac9d6080b7853d2b59b97d42079e1b2f121daf449b3b2e449
+ dhall-lang/tests/semantic-hash/success/prelude/List/concat/0A.dhall view
@@ -0,0 +1,5 @@+../../../../../../Prelude/List/concat.dhall Natural+[ [ 0, 1, 2 ]+, [ 3, 4 ]+, [ 5, 6, 7, 8 ]+]
+ dhall-lang/tests/semantic-hash/success/prelude/List/concat/0B.hash view
@@ -0,0 +1,1 @@+sha256:ae3a399d05bafcee80c088ca6c740f0c61c2a4c6fce6d7e4f4fa26560eac083f
+ dhall-lang/tests/semantic-hash/success/prelude/List/concat/1A.dhall view
@@ -0,0 +1,5 @@+../../../../../../Prelude/List/concat.dhall Natural+[ [] : List Natural+, [] : List Natural+, [] : List Natural+]
+ dhall-lang/tests/semantic-hash/success/prelude/List/concat/1B.hash view
@@ -0,0 +1,1 @@+sha256:d79a2e0e14809ab2dbd2d180e60da8e129a5fb197bdd0caed57e3828402e48a9
+ dhall-lang/tests/semantic-hash/success/prelude/List/concatMap/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/concatMap.dhall Natural Natural (λ(n : Natural) → [ n, n ]) [ 2, 3, 5 ]
+ dhall-lang/tests/semantic-hash/success/prelude/List/concatMap/0B.hash view
@@ -0,0 +1,1 @@+sha256:ea1f5046bcba6efb41bde23738d9a3f3aa2cda3dc722999d9e4f477eb9d1b12d
+ dhall-lang/tests/semantic-hash/success/prelude/List/concatMap/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/concatMap.dhall Natural Natural (λ(n : Natural) → [ n, n ]) ([] : List Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/List/concatMap/1B.hash view
@@ -0,0 +1,1 @@+sha256:d79a2e0e14809ab2dbd2d180e60da8e129a5fb197bdd0caed57e3828402e48a9
+ dhall-lang/tests/semantic-hash/success/prelude/List/filter/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/filter.dhall Natural Natural/even [ 2, 3, 5 ]
+ dhall-lang/tests/semantic-hash/success/prelude/List/filter/0B.hash view
@@ -0,0 +1,1 @@+sha256:988afbf26d86e95a4e6b78b0c344c9f987dcd5f7d7a7c541601bb1e9a01c9102
+ dhall-lang/tests/semantic-hash/success/prelude/List/filter/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/filter.dhall Natural Natural/odd [ 2, 3, 5 ]
+ dhall-lang/tests/semantic-hash/success/prelude/List/filter/1B.hash view
@@ -0,0 +1,1 @@+sha256:68248e1b69b249e6aeebcd36e7034f159b75d2931105fb4d41fc55d644b7ee8d
+ dhall-lang/tests/semantic-hash/success/prelude/List/fold/0A.dhall view
@@ -0,0 +1,6 @@+../../../../../../Prelude/List/fold.dhall+Natural+[ 2, 3, 5 ]+Natural+(λ(x : Natural) → λ(y : Natural) → x + y)+0
+ dhall-lang/tests/semantic-hash/success/prelude/List/fold/0B.hash view
@@ -0,0 +1,1 @@+sha256:d4428061b6fd69b6b45574603ac71060f9756a5c9a1642df322812e3a7ea858b
+ dhall-lang/tests/semantic-hash/success/prelude/List/fold/1A.dhall view
@@ -0,0 +1,7 @@+  λ(nil : Natural)+→ ../../../../../../Prelude/List/fold.dhall+  Natural+  [ 2, 3, 5 ]+  Natural+  (λ(x : Natural) → λ(y : Natural) → x + y)+  nil
+ dhall-lang/tests/semantic-hash/success/prelude/List/fold/1B.hash view
@@ -0,0 +1,1 @@+sha256:3bd732ae873cb107c3dfef4ae953f6480af310b27fda6b678b43569841e1012b
+ dhall-lang/tests/semantic-hash/success/prelude/List/fold/2A.dhall view
@@ -0,0 +1,4 @@+  λ(list : Type)+→ λ(cons : Natural → list → list)+→ λ(nil : list)+→ ../../../../../../Prelude/List/fold.dhall Natural [ 2, 3, 5 ] list cons nil
+ dhall-lang/tests/semantic-hash/success/prelude/List/fold/2B.hash view
@@ -0,0 +1,1 @@+sha256:186c485f65cbbf97aba127a1205a16ee1125ec279e727ff05d8f8ada624257c7
+ dhall-lang/tests/semantic-hash/success/prelude/List/generate/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/generate.dhall 5 Bool Natural/even
+ dhall-lang/tests/semantic-hash/success/prelude/List/generate/0B.hash view
@@ -0,0 +1,1 @@+sha256:0860d18cdc28bc4e7b081bf8c9891ab07e303e4f72b3439bb3a92d7dedd7e8fa
+ dhall-lang/tests/semantic-hash/success/prelude/List/generate/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/generate.dhall 0 Bool Natural/even
+ dhall-lang/tests/semantic-hash/success/prelude/List/generate/1B.hash view
@@ -0,0 +1,1 @@+sha256:fb7841e1b3b3e3511196b38df96e73ac7785edef663ea450f97b3c1322742d69
+ dhall-lang/tests/semantic-hash/success/prelude/List/head/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/head.dhall Natural [ 0, 1, 2 ]
+ dhall-lang/tests/semantic-hash/success/prelude/List/head/0B.hash view
@@ -0,0 +1,1 @@+sha256:7ac81b06d39113c93f17cc3d2aa55867453f68f35f58a4d577f5bacbb969225f
+ dhall-lang/tests/semantic-hash/success/prelude/List/head/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/head.dhall Natural ([] : List Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/List/head/1B.hash view
@@ -0,0 +1,1 @@+sha256:bfdc295856e05e3610d202d9c12f56f7c423de81cd6069f590786ca176b94df3
+ dhall-lang/tests/semantic-hash/success/prelude/List/indexed/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/indexed.dhall Bool [ True, False, True ]
+ dhall-lang/tests/semantic-hash/success/prelude/List/indexed/0B.hash view
@@ -0,0 +1,1 @@+sha256:7225a557384940f3f2f7f40e5e3e36384be7892c08a24e5467d0f75cd0dda9e1
+ dhall-lang/tests/semantic-hash/success/prelude/List/indexed/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/indexed.dhall Bool ([] : List Bool)
+ dhall-lang/tests/semantic-hash/success/prelude/List/indexed/1B.hash view
@@ -0,0 +1,1 @@+sha256:ff10538dd6bf3bf736bf38f54575e1ddd251aa1d6aad7c6ff6f4159bfc87cc4a
+ dhall-lang/tests/semantic-hash/success/prelude/List/iterate/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/iterate.dhall 10 Natural (λ(x : Natural) → x * 2) 1
+ dhall-lang/tests/semantic-hash/success/prelude/List/iterate/0B.hash view
@@ -0,0 +1,1 @@+sha256:577ea4905798b4fbd4803b3a7c82902594f0c3e5d84af46cec4514da9801760a
+ dhall-lang/tests/semantic-hash/success/prelude/List/iterate/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/iterate.dhall 0 Natural (λ(x : Natural) → x * 2) 1
+ dhall-lang/tests/semantic-hash/success/prelude/List/iterate/1B.hash view
@@ -0,0 +1,1 @@+sha256:d79a2e0e14809ab2dbd2d180e60da8e129a5fb197bdd0caed57e3828402e48a9
+ dhall-lang/tests/semantic-hash/success/prelude/List/last/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/last.dhall Natural [ 0, 1, 2 ]
+ dhall-lang/tests/semantic-hash/success/prelude/List/last/0B.hash view
@@ -0,0 +1,1 @@+sha256:1400a0fa058e1c8fc58926856000d82d99fad204bf48e36f54dccaafc0acd3a0
+ dhall-lang/tests/semantic-hash/success/prelude/List/last/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/last.dhall Natural ([] : List Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/List/last/1B.hash view
@@ -0,0 +1,1 @@+sha256:bfdc295856e05e3610d202d9c12f56f7c423de81cd6069f590786ca176b94df3
+ dhall-lang/tests/semantic-hash/success/prelude/List/length/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/length.dhall Natural [ 0, 1, 2 ]
+ dhall-lang/tests/semantic-hash/success/prelude/List/length/0B.hash view
@@ -0,0 +1,1 @@+sha256:15f52ecf91c94c1baac02d5a4964b2ed8fa401641a2c8a95e8306ec7c1e3b8d2
+ dhall-lang/tests/semantic-hash/success/prelude/List/length/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/length.dhall Natural ([] : List Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/List/length/1B.hash view
@@ -0,0 +1,1 @@+sha256:d0a48d41dcc572839faa9499b6c316b8d0d7115efac2ac770f062cd5fd6d0181
+ dhall-lang/tests/semantic-hash/success/prelude/List/map/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/map.dhall Natural Bool Natural/even [ 2, 3, 5 ]
+ dhall-lang/tests/semantic-hash/success/prelude/List/map/0B.hash view
@@ -0,0 +1,1 @@+sha256:aaf20d96e69473f836397764ec61b64a65dc5084ee33692ecd8b85ca63962827
+ dhall-lang/tests/semantic-hash/success/prelude/List/map/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/map.dhall Natural Bool Natural/even ([] : List Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/List/map/1B.hash view
@@ -0,0 +1,1 @@+sha256:fb7841e1b3b3e3511196b38df96e73ac7785edef663ea450f97b3c1322742d69
+ dhall-lang/tests/semantic-hash/success/prelude/List/null/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/null.dhall Natural [ 0, 1, 2 ]
+ dhall-lang/tests/semantic-hash/success/prelude/List/null/0B.hash view
@@ -0,0 +1,1 @@+sha256:2017ff3461395672aa0aa4f64894fd2f95a4b120e2690e8951656d79adc2eed2
+ dhall-lang/tests/semantic-hash/success/prelude/List/null/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/null.dhall Natural ([] : List Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/List/null/1B.hash view
@@ -0,0 +1,1 @@+sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ dhall-lang/tests/semantic-hash/success/prelude/List/replicate/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/replicate.dhall 9 Natural 1
+ dhall-lang/tests/semantic-hash/success/prelude/List/replicate/0B.hash view
@@ -0,0 +1,1 @@+sha256:4241079fe7c8a46be37831a35dedb60645c3a86a2ab24778e03c27c820813cdc
+ dhall-lang/tests/semantic-hash/success/prelude/List/replicate/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/replicate.dhall 0 Natural 1
+ dhall-lang/tests/semantic-hash/success/prelude/List/replicate/1B.hash view
@@ -0,0 +1,1 @@+sha256:d79a2e0e14809ab2dbd2d180e60da8e129a5fb197bdd0caed57e3828402e48a9
+ dhall-lang/tests/semantic-hash/success/prelude/List/reverse/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/reverse.dhall Natural [ 0, 1, 2 ]
+ dhall-lang/tests/semantic-hash/success/prelude/List/reverse/0B.hash view
@@ -0,0 +1,1 @@+sha256:ed586af4895ad8118e77976c6ee2fef5a39f69eb9378df32349c81fee2d61d4d
+ dhall-lang/tests/semantic-hash/success/prelude/List/reverse/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/reverse.dhall Natural ([] : List Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/List/reverse/1B.hash view
@@ -0,0 +1,1 @@+sha256:d79a2e0e14809ab2dbd2d180e60da8e129a5fb197bdd0caed57e3828402e48a9
+ dhall-lang/tests/semantic-hash/success/prelude/List/shifted/0A.dhall view
@@ -0,0 +1,15 @@+../../../../../../Prelude/List/shifted.dhall+Bool+[ [ { index = 0, value = True }+  , { index = 1, value = True }+  , { index = 2, value = False }+  ]+, [ { index = 0, value = False }+  , { index = 1, value = False }+  ]+, [ { index = 0, value = True }+  , { index = 1, value = True }+  , { index = 2, value = True }+  , { index = 3, value = True }+  ]+]
+ dhall-lang/tests/semantic-hash/success/prelude/List/shifted/0B.hash view
@@ -0,0 +1,1 @@+sha256:e5c27411e9b0692ac96e6914420f17748eda33d3854067675c6a3b3780fb15a6
+ dhall-lang/tests/semantic-hash/success/prelude/List/shifted/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/shifted.dhall Bool ([] : List (List { index : Natural, value : Bool }))
+ dhall-lang/tests/semantic-hash/success/prelude/List/shifted/1B.hash view
@@ -0,0 +1,1 @@+sha256:ff10538dd6bf3bf736bf38f54575e1ddd251aa1d6aad7c6ff6f4159bfc87cc4a
+ dhall-lang/tests/semantic-hash/success/prelude/List/unzip/0A.dhall view
@@ -0,0 +1,7 @@+../../../../../../Prelude/List/unzip.dhall+Text+Bool+[ { _1 = "ABC", _2 = True }+, { _1 = "DEF", _2 = False }+, { _1 = "GHI", _2 = True }+]
+ dhall-lang/tests/semantic-hash/success/prelude/List/unzip/0B.hash view
@@ -0,0 +1,1 @@+sha256:fffb0db166d08b99a1beb1650a3c9ee6e7bf6ce1054150bea4dae9b8ce5e4fbf
+ dhall-lang/tests/semantic-hash/success/prelude/List/unzip/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/unzip.dhall Text Bool ([] : List { _1 : Text, _2 : Bool })
+ dhall-lang/tests/semantic-hash/success/prelude/List/unzip/1B.hash view
@@ -0,0 +1,1 @@+sha256:c598ac5f10c7d20fe201f94ed5d9d18a847e89c65db9478492c930e5c42af710
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/build/0A.dhall view
@@ -0,0 +1,6 @@+../../../../../../Prelude/Natural/build.dhall+( λ(natural : Type)+→ λ(succ : natural → natural)+→ λ(zero : natural)+→ succ (succ (succ zero))+)
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/build/0B.hash view
@@ -0,0 +1,1 @@+sha256:15f52ecf91c94c1baac02d5a4964b2ed8fa401641a2c8a95e8306ec7c1e3b8d2
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/build/1A.dhall view
@@ -0,0 +1,6 @@+../../../../../../Prelude/Natural/build.dhall+( λ(natural : Type)+→ λ(succ : natural → natural)+→ λ(zero : natural)+→ zero+)
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/build/1B.hash view
@@ -0,0 +1,1 @@+sha256:d0a48d41dcc572839faa9499b6c316b8d0d7115efac2ac770f062cd5fd6d0181
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/enumerate/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/enumerate.dhall 10
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/enumerate/0B.hash view
@@ -0,0 +1,1 @@+sha256:a7af1902b53cc68a9613b659ebf58d06c840072625d14f9fde7eefa0e0f2add0
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/enumerate/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/enumerate.dhall 0
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/enumerate/1B.hash view
@@ -0,0 +1,1 @@+sha256:d79a2e0e14809ab2dbd2d180e60da8e129a5fb197bdd0caed57e3828402e48a9
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/even/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/even.dhall 3
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/even/0B.hash view
@@ -0,0 +1,1 @@+sha256:2017ff3461395672aa0aa4f64894fd2f95a4b120e2690e8951656d79adc2eed2
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/even/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/even.dhall 0
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/even/1B.hash view
@@ -0,0 +1,1 @@+sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/fold/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/fold.dhall 3 Natural (λ(x : Natural) → 5 * x) 1
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/fold/0B.hash view
@@ -0,0 +1,1 @@+sha256:39b0b6e0e0b616af4f20c7b06fefcd26dcdbd5be772d885fe73487574ec8b56b
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/fold/1A.dhall view
@@ -0,0 +1,1 @@+λ(zero : Natural) → ../../../../../../Prelude/Natural/fold.dhall 3 Natural (λ(x : Natural) → 5 * x) zero
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/fold/1B.hash view
@@ -0,0 +1,1 @@+sha256:c6ddb630f2abfcd78aa874079323ba2a9f80f548c5687346a0fcedff78d14f52
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/fold/2A.dhall view
@@ -0,0 +1,4 @@+  λ(natural : Type)+→ λ(succ : natural → natural)+→ λ(zero : natural)+→ ../../../../../../Prelude/Natural/fold.dhall 3 natural succ zero
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/fold/2B.hash view
@@ -0,0 +1,1 @@+sha256:08681d6fb9b1bb78be37f5a976186daa8fc39d0d1d3f7dbb716dc33937a6746d
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/isZero/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/isZero.dhall 2
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/isZero/0B.hash view
@@ -0,0 +1,1 @@+sha256:2017ff3461395672aa0aa4f64894fd2f95a4b120e2690e8951656d79adc2eed2
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/isZero/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/isZero.dhall 0
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/isZero/1B.hash view
@@ -0,0 +1,1 @@+sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/odd/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/odd.dhall 3
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/odd/0B.hash view
@@ -0,0 +1,1 @@+sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/odd/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/odd.dhall 0
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/odd/1B.hash view
@@ -0,0 +1,1 @@+sha256:2017ff3461395672aa0aa4f64894fd2f95a4b120e2690e8951656d79adc2eed2
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/product/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/product.dhall [ 2, 3, 5 ]
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/product/0B.hash view
@@ -0,0 +1,1 @@+sha256:49036d5d861d35d4aff797975a3447ebae71a9057951a03fc810ab8e8e00a498
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/product/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/product.dhall ([] : List Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/product/1B.hash view
@@ -0,0 +1,1 @@+sha256:d60d8415e36e86dae7f42933d3b0c4fe3ca238f057fba206c7e9fbf5d784fe15
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/show/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/show.dhall 3
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/show/0B.hash view
@@ -0,0 +1,1 @@+sha256:c8911e8084484ca0d468334986a19f0a11cc18b31f41f272e7d4ad2cd479ad39
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/show/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/show.dhall 0
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/show/1B.hash view
@@ -0,0 +1,1 @@+sha256:e3062e0493964ebaef8880667ad8a6289c277618c0b31141610abf5d69e7c9ea
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/sum/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/sum.dhall [ 2, 3, 5 ]
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/sum/0B.hash view
@@ -0,0 +1,1 @@+sha256:d4428061b6fd69b6b45574603ac71060f9756a5c9a1642df322812e3a7ea858b
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/sum/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/sum.dhall ([] : List Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/sum/1B.hash view
@@ -0,0 +1,1 @@+sha256:d0a48d41dcc572839faa9499b6c316b8d0d7115efac2ac770f062cd5fd6d0181
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/toDouble/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/toDouble.dhall 3
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/toDouble/0B.hash view
@@ -0,0 +1,1 @@+sha256:45b03fd4a48720ca71d4d12967cdde317c918d7c0295845cf9628784a124108d
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/toDouble/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/toDouble.dhall 0
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/toDouble/1B.hash view
@@ -0,0 +1,1 @@+sha256:3c213998cb56b97b31168d9dce02d084fb5f5103caef41fb6dc375f593749a7d
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/toInteger/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/toInteger.dhall 3
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/toInteger/0B.hash view
@@ -0,0 +1,1 @@+sha256:aa773179ef61a5d65c774bcc510806531ce8fa97c550961526153e42959e6f76
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/toInteger/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/toInteger.dhall 0
+ dhall-lang/tests/semantic-hash/success/prelude/Natural/toInteger/1B.hash view
@@ -0,0 +1,1 @@+sha256:5abe149a174ca99b6da92c97b0a7c8900a5f9acddb720bf7173eef877c6a187b
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/all/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/all.dhall Natural Natural/even (Some 3)
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/all/0B.hash view
@@ -0,0 +1,1 @@+sha256:2017ff3461395672aa0aa4f64894fd2f95a4b120e2690e8951656d79adc2eed2
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/all/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/all.dhall Natural Natural/even (None Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/all/1B.hash view
@@ -0,0 +1,1 @@+sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/any/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/any.dhall Natural Natural/even (Some 2)
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/any/0B.hash view
@@ -0,0 +1,1 @@+sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/any/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/any.dhall Natural Natural/even (None Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/any/1B.hash view
@@ -0,0 +1,1 @@+sha256:2017ff3461395672aa0aa4f64894fd2f95a4b120e2690e8951656d79adc2eed2
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/build/0A.dhall view
@@ -0,0 +1,7 @@+../../../../../../Prelude/Optional/build.dhall+Natural+( λ(optional : Type)+→ λ(some : Natural → optional)+→ λ(none : optional)+→ some 1+)
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/build/0B.hash view
@@ -0,0 +1,1 @@+sha256:033652a641ac54a27f52b874877889c6a9c7f8c435dae9f8e956e4d402d6f2c7
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/build/1A.dhall view
@@ -0,0 +1,7 @@+../../../../../../Prelude/Optional/build.dhall+Natural+( λ(optional : Type)+→ λ(some : Natural → optional)+→ λ(none : optional)+→ none+)
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/build/1B.hash view
@@ -0,0 +1,1 @@+sha256:bfdc295856e05e3610d202d9c12f56f7c423de81cd6069f590786ca176b94df3
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/concat/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/concat.dhall Natural (Some (Some 1))
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/concat/0B.hash view
@@ -0,0 +1,1 @@+sha256:033652a641ac54a27f52b874877889c6a9c7f8c435dae9f8e956e4d402d6f2c7
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/concat/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/concat.dhall Natural (Some (None Natural))
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/concat/1B.hash view
@@ -0,0 +1,1 @@+sha256:bfdc295856e05e3610d202d9c12f56f7c423de81cd6069f590786ca176b94df3
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/concat/2A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/concat.dhall Natural (None (Optional Natural))
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/concat/2B.hash view
@@ -0,0 +1,1 @@+sha256:bfdc295856e05e3610d202d9c12f56f7c423de81cd6069f590786ca176b94df3
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/filter/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/filter.dhall Natural Natural/even (Some 2)
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/filter/0B.hash view
@@ -0,0 +1,1 @@+sha256:1400a0fa058e1c8fc58926856000d82d99fad204bf48e36f54dccaafc0acd3a0
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/filter/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/filter.dhall Natural Natural/odd (Some 2)
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/filter/1B.hash view
@@ -0,0 +1,1 @@+sha256:bfdc295856e05e3610d202d9c12f56f7c423de81cd6069f590786ca176b94df3
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/fold/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/fold.dhall Natural (Some 2) Natural (λ(x : Natural) → x) 0
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/fold/0B.hash view
@@ -0,0 +1,1 @@+sha256:4caf97e8c445d4d4b5c5b992973e098ed4ae88a355915f5a59db640a589bc9cb
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/fold/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/fold.dhall Natural (None Natural) Natural (λ(x : Natural) → x) 0
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/fold/1B.hash view
@@ -0,0 +1,1 @@+sha256:d0a48d41dcc572839faa9499b6c316b8d0d7115efac2ac770f062cd5fd6d0181
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/head/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/head.dhall Natural [ None Natural, Some 1, Some 2 ]
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/head/0B.hash view
@@ -0,0 +1,1 @@+sha256:033652a641ac54a27f52b874877889c6a9c7f8c435dae9f8e956e4d402d6f2c7
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/head/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/head.dhall Natural [ None Natural, None Natural ]
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/head/1B.hash view
@@ -0,0 +1,1 @@+sha256:bfdc295856e05e3610d202d9c12f56f7c423de81cd6069f590786ca176b94df3
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/head/2A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/head.dhall Natural ([] : List (Optional Natural))
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/head/2B.hash view
@@ -0,0 +1,1 @@+sha256:bfdc295856e05e3610d202d9c12f56f7c423de81cd6069f590786ca176b94df3
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/last/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/last.dhall Natural [ None Natural, Some 1, Some 2 ]
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/last/0B.hash view
@@ -0,0 +1,1 @@+sha256:1400a0fa058e1c8fc58926856000d82d99fad204bf48e36f54dccaafc0acd3a0
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/last/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/last.dhall Natural [ None Natural, None Natural ]
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/last/1B.hash view
@@ -0,0 +1,1 @@+sha256:bfdc295856e05e3610d202d9c12f56f7c423de81cd6069f590786ca176b94df3
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/last/2A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/last.dhall Natural ([] : List (Optional Natural))
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/last/2B.hash view
@@ -0,0 +1,1 @@+sha256:bfdc295856e05e3610d202d9c12f56f7c423de81cd6069f590786ca176b94df3
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/length/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/length.dhall Natural (Some 2)
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/length/0B.hash view
@@ -0,0 +1,1 @@+sha256:d60d8415e36e86dae7f42933d3b0c4fe3ca238f057fba206c7e9fbf5d784fe15
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/length/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/length.dhall Natural (None Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/length/1B.hash view
@@ -0,0 +1,1 @@+sha256:d0a48d41dcc572839faa9499b6c316b8d0d7115efac2ac770f062cd5fd6d0181
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/map/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/map.dhall Natural Bool Natural/even (Some 3)
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/map/0B.hash view
@@ -0,0 +1,1 @@+sha256:3af5b2f9dcc58e7950e2f0281f796de2ac5e87554ae758e38c36cd55cf53743e
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/map/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/map.dhall Natural Bool Natural/even (None Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/map/1B.hash view
@@ -0,0 +1,1 @@+sha256:2c9884f8336ed425b13068919b216c42be286636c657faa15b911382436b3f00
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/null/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/null.dhall Natural (Some 2)
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/null/0B.hash view
@@ -0,0 +1,1 @@+sha256:2017ff3461395672aa0aa4f64894fd2f95a4b120e2690e8951656d79adc2eed2
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/null/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/null.dhall Natural (None Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/null/1B.hash view
@@ -0,0 +1,1 @@+sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/toList/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/toList.dhall Natural (Some 1)
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/toList/0B.hash view
@@ -0,0 +1,1 @@+sha256:75be41333b1ef7a6f5c5cfbcd6097681f3968736dc393b9bf53b2e609564217f
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/toList/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/toList.dhall Natural (None Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/toList/1B.hash view
@@ -0,0 +1,1 @@+sha256:d79a2e0e14809ab2dbd2d180e60da8e129a5fb197bdd0caed57e3828402e48a9
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/unzip/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/unzip.dhall Text Bool (Some { _1 = "ABC", _2 = True })
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/unzip/0B.hash view
@@ -0,0 +1,1 @@+sha256:5604f6ef6cf7385166101c61738c34a84983f1b7b4695858fa2068fc669eb2c1
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/unzip/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/unzip.dhall Text Bool (None { _1 : Text, _2 : Bool })
+ dhall-lang/tests/semantic-hash/success/prelude/Optional/unzip/1B.hash view
@@ -0,0 +1,1 @@+sha256:6de82c54048538c97063c9ae31919b4ca21018ae7119bc123508c136ee653280
+ dhall-lang/tests/semantic-hash/success/prelude/Text/concat/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Text/concat.dhall [ "ABC", "DEF", "GHI" ]
+ dhall-lang/tests/semantic-hash/success/prelude/Text/concat/0B.hash view
@@ -0,0 +1,1 @@+sha256:1f73cf8a6efa724376c3342f9e0104c499e16420732b8c25efc6ab1c18979772
+ dhall-lang/tests/semantic-hash/success/prelude/Text/concat/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Text/concat.dhall ([] : List Text)
+ dhall-lang/tests/semantic-hash/success/prelude/Text/concat/1B.hash view
@@ -0,0 +1,1 @@+sha256:f08ed5225480d827ff3ce74b756afa6330f66d974d6f0d6160d767b5c45642aa
+ dhall-lang/tests/semantic-hash/success/prelude/Text/concatMap/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Text/concatMap.dhall Natural (λ(n : Natural) → "${Natural/show n} ") [ 0, 1, 2 ]
+ dhall-lang/tests/semantic-hash/success/prelude/Text/concatMap/0B.hash view
@@ -0,0 +1,1 @@+sha256:fa7f18d0522f120dbf229ff0a55f96792ce76613ba17611c53f3f5efd81df510
+ dhall-lang/tests/semantic-hash/success/prelude/Text/concatMap/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Text/concatMap.dhall Natural (λ(n : Natural) → "${Natural/show n} ") ([] : List Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/Text/concatMap/1B.hash view
@@ -0,0 +1,1 @@+sha256:f08ed5225480d827ff3ce74b756afa6330f66d974d6f0d6160d767b5c45642aa
+ dhall-lang/tests/semantic-hash/success/prelude/Text/concatMapSep/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Text/concatMapSep.dhall ", " Natural Natural/show [ 0, 1, 2 ]
+ dhall-lang/tests/semantic-hash/success/prelude/Text/concatMapSep/0B.hash view
@@ -0,0 +1,1 @@+sha256:952e63727a69b5f2db65645167c3a8f60dbc350608562a1c90423c819a1b5baf
+ dhall-lang/tests/semantic-hash/success/prelude/Text/concatMapSep/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Text/concatMapSep.dhall ", " Natural Natural/show ([] : List Natural)
+ dhall-lang/tests/semantic-hash/success/prelude/Text/concatMapSep/1B.hash view
@@ -0,0 +1,1 @@+sha256:f08ed5225480d827ff3ce74b756afa6330f66d974d6f0d6160d767b5c45642aa
+ dhall-lang/tests/semantic-hash/success/prelude/Text/concatSep/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Text/concatSep.dhall ", " [ "ABC", "DEF", "GHI" ]
+ dhall-lang/tests/semantic-hash/success/prelude/Text/concatSep/0B.hash view
@@ -0,0 +1,1 @@+sha256:151ad6d86cced932c9ed6fa5d69b88fb47e160a13762f4d92dcb1e847ccd30d6
+ dhall-lang/tests/semantic-hash/success/prelude/Text/concatSep/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Text/concatSep.dhall ", " ([] : List Text)
+ dhall-lang/tests/semantic-hash/success/prelude/Text/concatSep/1B.hash view
@@ -0,0 +1,1 @@+sha256:f08ed5225480d827ff3ce74b756afa6330f66d974d6f0d6160d767b5c45642aa
+ dhall-lang/tests/semantic-hash/success/prelude/Text/show/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Text/show.dhall "ABC"
+ dhall-lang/tests/semantic-hash/success/prelude/Text/show/0B.hash view
@@ -0,0 +1,1 @@+sha256:8dffa347e98424c7b1e91e3e3758fc203a4e52fd990dc4b050da18cdb39655d3
+ dhall-lang/tests/semantic-hash/success/prelude/Text/show/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Text/show.dhall "\u0000 \$ \\ \n \u263a"
+ dhall-lang/tests/semantic-hash/success/prelude/Text/show/1B.hash view
@@ -0,0 +1,1 @@+sha256:92655b5ee59ddfb1decfd19cf8b37e8f2dd5dbd317f55bcbb780bf6ed2010b0a
+ dhall-lang/tests/semantic-hash/success/remoteSystemsA.dhall view
@@ -0,0 +1,51 @@+let Text/concatMap = ../../../Prelude/Text/concatMap++let Text/concatSep = ../../../Prelude/Text/concatSep++let Row =+      { cores :+          Natural+      , host :+          Text+      , key :+          Text+      , mandatoryFeatures :+          List Text+      , platforms :+          List Text+      , speedFactor :+          Natural+      , supportedFeatures :+          List Text+      , user :+          Optional Text+      }++let renderRow =+        λ ( row+          : Row+          )+      → let host =+              merge+                { None = row.host+                , Some = λ(user : Text) → "${user}@${row.host}"+                }+                row.user+        +        let platforms = Text/concatSep "," row.platforms+        +        let key = row.key+        +        let cores = Integer/show (Natural/toInteger row.cores)+        +        let speedFactor = Integer/show (Natural/toInteger row.speedFactor)+        +        let supportedFeatures = Text/concatSep "," row.supportedFeatures+        +        let mandatoryFeatures = Text/concatSep "," row.mandatoryFeatures+        +        in  ''+            ${host} ${platforms} ${key} ${cores} ${speedFactor} ${supportedFeatures} ${mandatoryFeatures}+            ''++in  Text/concatMap Row renderRow
+ dhall-lang/tests/semantic-hash/success/remoteSystemsB.hash view
@@ -0,0 +1,1 @@+sha256:573b0d8fbc28c09c155cf239963b6ba71941aace25e23806043017f7fe75098b
+ dhall-lang/tests/semantic-hash/success/simple/doubleShowA.dhall view
@@ -0,0 +1,6 @@+{ example0 = Double/show -0.42+, example1 = Double/show 13.37+, example2 = Double/show NaN+, example3 = Double/show Infinity+, example4 = Double/show -Infinity+}
+ dhall-lang/tests/semantic-hash/success/simple/doubleShowB.hash view
@@ -0,0 +1,1 @@+sha256:519ea07f25f759795d4326f06a97401fe0a5efe7823139976d1158c939ee6176
+ dhall-lang/tests/semantic-hash/success/simple/enumA.dhall view
@@ -0,0 +1,8 @@+let Role = < Wizard | Fighter | Rogue >++let show : Role → Text+         =+        λ(x : Role)+      → merge { Wizard = "Wizard", Fighter = "Fighter", Rogue = "Rogue" } x++in  show Role.Wizard
+ dhall-lang/tests/semantic-hash/success/simple/enumB.hash view
@@ -0,0 +1,1 @@+sha256:0e6e479638f87eca04805548d70b5de9d22c5359e7d84ccbcfe148577bc25a4e
+ dhall-lang/tests/semantic-hash/success/simple/integerShowA.dhall view
@@ -0,0 +1,4 @@+{ example0 = Integer/show +1337+, example1 = Integer/show -42+, example2 = Integer/show +0+}
+ dhall-lang/tests/semantic-hash/success/simple/integerShowB.hash view
@@ -0,0 +1,1 @@+sha256:7ff01ad1c68550be713834548385874f38fd7b989e3c4b8cad7125bc266e2bb3
+ dhall-lang/tests/semantic-hash/success/simple/integerToDoubleA.dhall view
@@ -0,0 +1,10 @@+[ Integer/toDouble +179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497792+, Integer/toDouble +179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497791+, Integer/toDouble +179769313486231560835325876058105298516207002341652166261661174625869553267292326574530099287946549246750631490335877017522087105926987962906277604735569213290190919152394180476217125334960946356387261286640198029037799514183602981511756283727771403830521483963923935633133642802139091669457927874464075218945+, Integer/toDouble +179769313486231560835325876058105298516207002341652166261661174625869553267292326574530099287946549246750631490335877017522087105926987962906277604735569213290190919152394180476217125334960946356387261286640198029037799514183602981511756283727771403830521483963923935633133642802139091669457927874464075218944++, Integer/toDouble -179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497792+, Integer/toDouble -179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497791+, Integer/toDouble -179769313486231560835325876058105298516207002341652166261661174625869553267292326574530099287946549246750631490335877017522087105926987962906277604735569213290190919152394180476217125334960946356387261286640198029037799514183602981511756283727771403830521483963923935633133642802139091669457927874464075218945+, Integer/toDouble -179769313486231560835325876058105298516207002341652166261661174625869553267292326574530099287946549246750631490335877017522087105926987962906277604735569213290190919152394180476217125334960946356387261286640198029037799514183602981511756283727771403830521483963923935633133642802139091669457927874464075218944+]
+ dhall-lang/tests/semantic-hash/success/simple/integerToDoubleB.hash view
@@ -0,0 +1,1 @@+sha256:439d81a4aee03a27da069772c4ea51d64c025faac1a2e749734cc5e4cf0f2484
+ dhall-lang/tests/semantic-hash/success/simple/letletA.dhall view
@@ -0,0 +1,3 @@+let l = λ(n : Natural) → λ(m : Natural) → λ(x : Natural) → n + m * x+let f = l 2 3+in  f 445
+ dhall-lang/tests/semantic-hash/success/simple/letletB.hash view
@@ -0,0 +1,1 @@+sha256:97285916da4ee4a1e108af044b449edcdfb818c2f55aefd64f0af76b347da16d
+ dhall-lang/tests/semantic-hash/success/simple/listBuildA.dhall view
@@ -0,0 +1,22 @@+{ example0 =+    List/build+    Bool+    (   λ(list : Type)+      → λ(cons : Bool → list → list)+      → λ(nil : list)+      → cons True (cons False nil)+    )+, example1 =+    List/build+    Bool+    (λ(x : Type) → λ(x : Bool → x → x) → λ(x : x@1) → x@1 True (x@1 False x))+, example2 =+      λ(id : ∀(a : Type) → a → a)+    → List/build+      Bool+      (   λ(list : Type)+        → λ(cons : Bool → list → list)+        → λ(nil : list)+        → id list (cons True (cons False nil))+      )+}
+ dhall-lang/tests/semantic-hash/success/simple/listBuildB.hash view
@@ -0,0 +1,1 @@+sha256:f8f03d5be6563b275253b4d995499e783112ff98ed231855e9152ba45970f8c7
+ dhall-lang/tests/semantic-hash/success/simple/multiLineA.dhall view
@@ -0,0 +1,4 @@+''+ foo+bar+''
+ dhall-lang/tests/semantic-hash/success/simple/multiLineB.hash view
@@ -0,0 +1,1 @@+sha256:2ab4fb081094ad6729186b7cd8a0ec67f7845bbea59ec5a484bff2de42390137
+ dhall-lang/tests/semantic-hash/success/simple/naturalBuildA.dhall view
@@ -0,0 +1,18 @@+{ example0 =+    Natural/build+    (   λ(natural : Type)+      → λ(succ : natural → natural)+      → λ(zero : natural)+      → succ zero+    )+, example1 =+    Natural/build (λ(x : Type) → λ(x : x → x) → λ(x : x@1) → x@1 x)+, example2 =+      λ(id : ∀(a : Type) → a → a)+    → Natural/build+      (   λ(natural : Type)+        → λ(succ : natural → natural)+        → λ(zero : natural)+        → id natural (succ zero)+      )+}
+ dhall-lang/tests/semantic-hash/success/simple/naturalBuildB.hash view
@@ -0,0 +1,1 @@+sha256:3e14f3cbed2ddcc78cb9bf66bf2372c2059fd6c4b406ca309a05b89b7f62b011
+ dhall-lang/tests/semantic-hash/success/simple/naturalPlusA.dhall view
@@ -0,0 +1,1 @@+1 + 2
+ dhall-lang/tests/semantic-hash/success/simple/naturalPlusB.hash view
@@ -0,0 +1,1 @@+sha256:15f52ecf91c94c1baac02d5a4964b2ed8fa401641a2c8a95e8306ec7c1e3b8d2
+ dhall-lang/tests/semantic-hash/success/simple/naturalShowA.dhall view
@@ -0,0 +1,1 @@+Natural/show 42
+ dhall-lang/tests/semantic-hash/success/simple/naturalShowB.hash view
@@ -0,0 +1,1 @@+sha256:3d1abfe685ff9abcf5e1a6bcce9b1a8374fc8ac176c22ef3e0188bd29e7d8c6d
+ dhall-lang/tests/semantic-hash/success/simple/naturalToIntegerA.dhall view
@@ -0,0 +1,1 @@+Natural/toInteger 1
+ dhall-lang/tests/semantic-hash/success/simple/naturalToIntegerB.hash view
@@ -0,0 +1,1 @@+sha256:d2cbb0e226f332ea76d63b3ae4332780c4051d1388d3e190debd5441f4595a04
+ dhall-lang/tests/semantic-hash/success/simple/sortOperatorA.dhall view
@@ -0,0 +1,1 @@+{ b = 2 } // { a = 1 }
+ dhall-lang/tests/semantic-hash/success/simple/sortOperatorB.hash view
@@ -0,0 +1,1 @@+sha256:97090822fa42ff0245484a518e2457f85271f4c36fc9462b82498d85b2cc98fc
+ dhall-lang/tests/semantic-hash/success/simplifications/andA.dhall view
@@ -0,0 +1,6 @@+{ example0 = λ(x : Bool) → x && True+, example1 = λ(x : Bool) → True && x+, example2 = λ(x : Bool) → x && False+, example3 = λ(x : Bool) → False && x+, example4 = λ(x : Bool) → x && x+}
+ dhall-lang/tests/semantic-hash/success/simplifications/andB.hash view
@@ -0,0 +1,1 @@+sha256:ceac399e820b2a86c65077e07e77bb62f10253fda02a51e438457adf4368b580
+ dhall-lang/tests/semantic-hash/success/simplifications/eqA.dhall view
@@ -0,0 +1,4 @@+{ example0 = λ(x : Bool) → x == True+, example1 = λ(x : Bool) → True == x+, example2 = λ(x : Bool) → x == x+}
+ dhall-lang/tests/semantic-hash/success/simplifications/eqB.hash view
@@ -0,0 +1,1 @@+sha256:5524bd7e3ecdeaa98a25f51f40a1cb33896c2e3e0e21e14c939d17dac946fa4d
+ dhall-lang/tests/semantic-hash/success/simplifications/ifThenElseA.dhall view
@@ -0,0 +1,3 @@+{ example0 = λ(x : Bool) → if x then True else False+, example1 = λ(x : Bool) → λ(y : Text) → if x then y else y+}
+ dhall-lang/tests/semantic-hash/success/simplifications/ifThenElseB.hash view
@@ -0,0 +1,1 @@+sha256:40b3cdc4cc8f2ff9b733e5e8d8613ec8c3d17fc11f22cfd96d8109765c15add5
+ dhall-lang/tests/semantic-hash/success/simplifications/neA.dhall view
@@ -0,0 +1,4 @@+{ example0 = λ(x : Bool) → x != False+, example1 = λ(x : Bool) → False != x+, example2 = λ(x : Bool) → x != x+}
+ dhall-lang/tests/semantic-hash/success/simplifications/neB.hash view
@@ -0,0 +1,1 @@+sha256:69d11e754a064f8abe927e5df446896372a6367135e08c52b5c2274e3bd03bc7
+ dhall-lang/tests/semantic-hash/success/simplifications/orA.dhall view
@@ -0,0 +1,6 @@+{ example0 = λ(x : Bool) → x || True+, example1 = λ(x : Bool) → True || x+, example2 = λ(x : Bool) → x || False+, example3 = λ(x : Bool) → False || x+, example4 = λ(x : Bool) → x || x+}
+ dhall-lang/tests/semantic-hash/success/simplifications/orB.hash view
@@ -0,0 +1,1 @@+sha256:41437a8eb5753b2d340fc27cc192265459da57cd65d487447a261f2eede2f5ef
+ dhall-lang/tests/type-inference/failure/DateApplyTime.dhall view
@@ -0,0 +1,3 @@+-- This parses, but will fail to type-check, because in the absence of the `T`+-- it is interpreted as a `Date` applied to a `Time`+2020-01-01 12:00:00
+ dhall-lang/tests/type-inference/failure/SortInLet.dhall view
@@ -0,0 +1,1 @@+let x = Sort in 0
+ dhall-lang/tests/type-inference/failure/hurkensParadox.dhall view
@@ -0,0 +1,49 @@+    let bottom : Type = ∀(any : Type) → any++in  let not : Type → Type = λ(p : Type) → p → bottom++in  let pow = λ(X : Kind) → X → Type++in  let U = ∀(X : Kind) → (pow (pow X) → X) → pow (pow X)++in  let tau+        : pow (pow U) → U+        =   λ(t : pow (pow U))+          → λ(X : Kind)+          → λ(f : pow (pow X) → X)+          → λ(p : pow X)+          → t (λ(x : U) → p (f (x X f)))++in  let sigma : U → pow (pow U) = λ(s : U) → s U (λ(t : pow (pow U)) → tau t)++in  let Delta+        : pow U+        = λ(y : U) → not (∀(p : pow U) → sigma y p → p (tau (sigma y)))++in  let Omega : U = tau (λ(p : pow U) → ∀(x : U) → sigma x p → p x)++in  let Theta : Type = ∀(p : pow U) → (∀(x : U) → sigma x p → p x) → p Omega++in  let D : Type = ∀(p : pow U) → sigma Omega p → p (tau (sigma Omega))++in  let lem1+        : ∀(p : pow U) → (∀(x : U) → sigma x p → p x) → p Omega+        =   λ(p : pow U)+          → λ(t1 : ∀(x : U) → sigma x p → p x)+          → t1 Omega (λ(x : U) → t1 (tau (sigma x)))++in  let lem3 : D = λ(p : pow U) → lem1 (λ(y : U) → p (tau (sigma y)))++in  let lem2+        : not D+        = lem1+          Delta+          (   λ(x : U)+            → λ(H2 : sigma x Delta)+            → λ(H3 : ∀(p : pow U) → sigma x p → p (tau (sigma x)))+            → H3 Delta H2 (λ(pp : pow U) → H3 (λ(y : U) → pp (tau (sigma y))))+          )++in  let evidence : bottom = lem2 lem3++in  evidence
+ dhall-lang/tests/type-inference/failure/recordOfKind.dhall view
@@ -0,0 +1,1 @@+{ a = Kind }
+ dhall-lang/tests/type-inference/failure/unit/AnnotationRecordWrongFieldName.dhall view
@@ -0,0 +1,1 @@+{ x = 1 } : { y : Natural }
+ dhall-lang/tests/type-inference/failure/unit/AnnotationRecordWrongFieldType.dhall view
@@ -0,0 +1,1 @@+{ x = 1 } : { x : Text }
+ dhall-lang/tests/type-inference/failure/unit/AssertAlphaTrap.dhall view
@@ -0,0 +1,1 @@+assert : (\(_: Bool) -> _) === (\(x: Bool) -> _)
+ dhall-lang/tests/type-inference/failure/unit/AssertAlphaTrap2.dhall view
@@ -0,0 +1,1 @@+\(_: Bool) -> assert : (\(_: Bool) -> _) === (\(x: Bool) -> _)
+ dhall-lang/tests/type-inference/failure/unit/AssertDoubleZeros.dhall view
@@ -0,0 +1,1 @@+assert : -0.0 ≡ +0.0
+ dhall-lang/tests/type-inference/failure/unit/AssertNotEquivalence.dhall view
@@ -0,0 +1,1 @@+assert : Bool
+ dhall-lang/tests/type-inference/failure/unit/AssertTriviallyFalse.dhall view
@@ -0,0 +1,1 @@+assert : 1 === 2
+ dhall-lang/tests/type-inference/failure/unit/CompletionMissingRequiredField.dhall view
@@ -0,0 +1,6 @@+let Example =+      { Type = { name : Text, id : Optional Natural }+      , default = { id = None Natural }+      }++in  Example::{=}
+ dhall-lang/tests/type-inference/failure/unit/CompletionWithWrongDefaultType.dhall view
@@ -0,0 +1,6 @@+let Example =+      { Type = { name : Text, id : Optional Natural }+      , default = { name = True, id = None Natural }+      }++in  Example::{=}
+ dhall-lang/tests/type-inference/failure/unit/CompletionWithWrongFieldName.dhall view
@@ -0,0 +1,6 @@+let Example =+      { Type = { name : Text, id : Optional Natural }+      , default = { name = "", id = None Natural }+      }++in  Example::{ nam = "John Doe" }
+ dhall-lang/tests/type-inference/failure/unit/CompletionWithWrongOverridenType.dhall view
@@ -0,0 +1,6 @@+let Example =+      { Type = { name : Text, id : Optional Natural }+      , default = { name = "", id = None Natural }+      }++in  Example::{ name = True }
+ dhall-lang/tests/type-inference/failure/unit/EmptyToMap.dhall view
@@ -0,0 +1,1 @@+toMap {=}
+ dhall-lang/tests/type-inference/failure/unit/EquivalenceNotSameType.dhall view
@@ -0,0 +1,1 @@+1 === False
+ dhall-lang/tests/type-inference/failure/unit/EquivalenceNotTerms.dhall view
@@ -0,0 +1,1 @@+Bool === Bool
+ dhall-lang/tests/type-inference/failure/unit/FunctionApplicationArgumentNotMatch.dhall view
@@ -0,0 +1,1 @@+(λ(_ : Natural) → _) True
+ dhall-lang/tests/type-inference/failure/unit/FunctionApplicationIsNotFunction.dhall view
@@ -0,0 +1,1 @@+True True
+ dhall-lang/tests/type-inference/failure/unit/FunctionArgumentTypeNotAType.dhall view
@@ -0,0 +1,1 @@+λ(_ : 1) → _
+ dhall-lang/tests/type-inference/failure/unit/FunctionTypeArgumentTypeNotAType.dhall view
@@ -0,0 +1,1 @@+2 → _
+ dhall-lang/tests/type-inference/failure/unit/FunctionTypeKindSort.dhall view
@@ -0,0 +1,1 @@+Kind → Sort
+ dhall-lang/tests/type-inference/failure/unit/FunctionTypeOutputTypeNotAType.dhall view
@@ -0,0 +1,1 @@+Bool -> 1
+ dhall-lang/tests/type-inference/failure/unit/FunctionTypeTypeSort.dhall view
@@ -0,0 +1,1 @@+Type → Sort
+ dhall-lang/tests/type-inference/failure/unit/HeterogenousToMap.dhall view
@@ -0,0 +1,1 @@+toMap { foo= 1, bar= "Bar" }
+ dhall-lang/tests/type-inference/failure/unit/IfBranchesNotMatch.dhall view
@@ -0,0 +1,1 @@+if True then 1 else ""
+ dhall-lang/tests/type-inference/failure/unit/IfBranchesNotTermTypeOrKind.dhall view
@@ -0,0 +1,1 @@+if True then Kind else Kind
+ dhall-lang/tests/type-inference/failure/unit/IfNotBool.dhall view
@@ -0,0 +1,1 @@+if 1 then 1 else 1
+ dhall-lang/tests/type-inference/failure/unit/LetInSort.dhall view
@@ -0,0 +1,1 @@+\(x: let x = 0 in Sort) -> 1
+ dhall-lang/tests/type-inference/failure/unit/LetWithNonterminatingAnnotation.dhall view
@@ -0,0 +1,14 @@+-- When you check if an inferred type is equivalent to an annotation,+-- you must alpha-beta-normalize both sides first.  But it is not safe+-- to beta-normalise an expression which hasn't first been+-- typechecked.+--+-- This test contains an annotation which doesn't typecheck, and+-- which, when beta-normalized, doesn't terminate.  It exists to+-- verify that implementations typecheck the annotation before+-- checking equivalence.+let a+    : (λ(x : Natural) → x x) (λ(x : Natural) → x x)+    = 3++in  5
+ dhall-lang/tests/type-inference/failure/unit/LetWithWrongAnnotation.dhall view
@@ -0,0 +1,1 @@+let x : Natural = True in True
+ dhall-lang/tests/type-inference/failure/unit/ListLiteralEmptyNotType.dhall view
@@ -0,0 +1,1 @@+[] : List Type
+ dhall-lang/tests/type-inference/failure/unit/ListLiteralNotType.dhall view
@@ -0,0 +1,1 @@+[ Bool ]
+ dhall-lang/tests/type-inference/failure/unit/ListLiteralTypesNotMatch.dhall view
@@ -0,0 +1,1 @@+[ True, 1 ]
+ dhall-lang/tests/type-inference/failure/unit/MergeAlternativeHasNoHandler.dhall view
@@ -0,0 +1,1 @@+merge {=} (< x : Bool >.x True)
+ dhall-lang/tests/type-inference/failure/unit/MergeAnnotationMismatch.dhall view
@@ -0,0 +1,1 @@+merge { x = 0 } < x >.x : Bool
+ dhall-lang/tests/type-inference/failure/unit/MergeAnnotationNotType.dhall view
@@ -0,0 +1,1 @@+merge {=} <> : Type
+ dhall-lang/tests/type-inference/failure/unit/MergeBool.dhall view
@@ -0,0 +1,1 @@+\(x: { True: Natural, False: Natural }) -> merge x True
+ dhall-lang/tests/type-inference/failure/unit/MergeEmptyNeedsDirectAnnotation1.dhall view
@@ -0,0 +1,1 @@+\(x: <>) -> (merge {=} x) : Bool
+ dhall-lang/tests/type-inference/failure/unit/MergeEmptyNeedsDirectAnnotation2.dhall view
@@ -0,0 +1,1 @@+\(x: <>) -> let y: Bool = merge {=} x in 1
+ dhall-lang/tests/type-inference/failure/unit/MergeEmptyWithoutAnnotation.dhall view
@@ -0,0 +1,1 @@+merge {=} <>
+ dhall-lang/tests/type-inference/failure/unit/MergeHandlerFreeVar.dhall view
@@ -0,0 +1,1 @@+merge { x = None } (<x: Type>.x Bool)
+ dhall-lang/tests/type-inference/failure/unit/MergeHandlerNotFunction.dhall view
@@ -0,0 +1,1 @@+merge { x = True } (< x : Bool >.x True)
+ dhall-lang/tests/type-inference/failure/unit/MergeHandlerNotInUnion.dhall view
@@ -0,0 +1,1 @@+merge { x = λ(_ : Bool) → _ } <> : Bool
+ dhall-lang/tests/type-inference/failure/unit/MergeHandlerNotMatchAlternativeType.dhall view
@@ -0,0 +1,1 @@+merge { x = λ(_ : Bool) → _ } (< x : Natural >.x 1)
+ dhall-lang/tests/type-inference/failure/unit/MergeHandlersWithDifferentType.dhall view
@@ -0,0 +1,1 @@+merge { x = λ(_ : Bool) → _, y = λ(_ : Natural) → _ } (< x : Bool | y : Natural >.x True)
+ dhall-lang/tests/type-inference/failure/unit/MergeLhsNotRecord.dhall view
@@ -0,0 +1,1 @@+merge True < x >.x
+ dhall-lang/tests/type-inference/failure/unit/MergeMissingHandler1.dhall view
@@ -0,0 +1,1 @@+merge {=} <x>.x
+ dhall-lang/tests/type-inference/failure/unit/MergeMissingHandler2.dhall view
@@ -0,0 +1,1 @@+merge { x = 0 } <x | y>.x
+ dhall-lang/tests/type-inference/failure/unit/MergeRhsNotUnion.dhall view
@@ -0,0 +1,1 @@+merge {=} True
+ dhall-lang/tests/type-inference/failure/unit/MergeUnusedHandler.dhall view
@@ -0,0 +1,1 @@+merge { x = 1, y = 2 } < x >.x
+ dhall-lang/tests/type-inference/failure/unit/MistypedToMap1.dhall view
@@ -0,0 +1,1 @@+toMap { foo= 1, bar= 4 } : Natural
+ dhall-lang/tests/type-inference/failure/unit/MistypedToMap2.dhall view
@@ -0,0 +1,1 @@+toMap { foo= 1, bar= 4 } : List Natural
+ dhall-lang/tests/type-inference/failure/unit/MistypedToMap3.dhall view
@@ -0,0 +1,1 @@+toMap { foo= 1, bar= 4 } : List { mapKey : Natural, mapValue : Natural }
+ dhall-lang/tests/type-inference/failure/unit/MistypedToMap4.dhall view
@@ -0,0 +1,1 @@+toMap { foo= 1, bar= 4 } : List { mapKey : Text, mapValue : Text }
+ dhall-lang/tests/type-inference/failure/unit/NaturalSubtractNotNatural.dhall view
@@ -0,0 +1,1 @@+Natural/subtract True True
+ dhall-lang/tests/type-inference/failure/unit/NestedAnnotInnerWrong.dhall view
@@ -0,0 +1,1 @@+(0 : Bool) : Natural
+ dhall-lang/tests/type-inference/failure/unit/NestedAnnotOuterWrong.dhall view
@@ -0,0 +1,1 @@+(0 : Natural) : Bool
+ dhall-lang/tests/type-inference/failure/unit/NonRecordToMap.dhall view
@@ -0,0 +1,1 @@+toMap "text"
+ dhall-lang/tests/type-inference/failure/unit/OperatorAndNotBool.dhall view
@@ -0,0 +1,1 @@+1 && 1
+ dhall-lang/tests/type-inference/failure/unit/OperatorEqualNotBool.dhall view
@@ -0,0 +1,1 @@+1 == 1
+ dhall-lang/tests/type-inference/failure/unit/OperatorListConcatenateLhsNotList.dhall view
@@ -0,0 +1,1 @@+1 # [ True ]
+ dhall-lang/tests/type-inference/failure/unit/OperatorListConcatenateListsNotMatch.dhall view
@@ -0,0 +1,1 @@+[ True ] # [ 1 ]
+ dhall-lang/tests/type-inference/failure/unit/OperatorListConcatenateNotListsButMatch.dhall view
@@ -0,0 +1,1 @@+1 # 2
+ dhall-lang/tests/type-inference/failure/unit/OperatorListConcatenateRhsNotList.dhall view
@@ -0,0 +1,1 @@+[ True ] # 1
+ dhall-lang/tests/type-inference/failure/unit/OperatorNotEqualNotBool.dhall view
@@ -0,0 +1,1 @@+1 != 1
+ dhall-lang/tests/type-inference/failure/unit/OperatorOrNotBool.dhall view
@@ -0,0 +1,1 @@+1 || 1
+ dhall-lang/tests/type-inference/failure/unit/OperatorPlusNotNatural.dhall view
@@ -0,0 +1,1 @@+True + True
+ dhall-lang/tests/type-inference/failure/unit/OperatorTextConcatenateLhsNotText.dhall view
@@ -0,0 +1,1 @@+1 ++ ""
+ dhall-lang/tests/type-inference/failure/unit/OperatorTextConcatenateRhsNotText.dhall view
@@ -0,0 +1,1 @@+"" ++ 1
+ dhall-lang/tests/type-inference/failure/unit/OperatorTimesNotNatural.dhall view
@@ -0,0 +1,1 @@+True * True
+ dhall-lang/tests/type-inference/failure/unit/OptionalDeprecatedSyntaxAbsent.dhall view
@@ -0,0 +1,1 @@+[] : Optional Bool
+ dhall-lang/tests/type-inference/failure/unit/OptionalDeprecatedSyntaxPresent.dhall view
@@ -0,0 +1,1 @@+[ 1 ] : Optional Natural
+ dhall-lang/tests/type-inference/failure/unit/RecordLitDuplicateFieldsAbstract.dhall view
@@ -0,0 +1,13 @@+{-  This test illustrates that duplicate fields need not be literals in order+    to be properly normalized.  One or both of the duplicate fields can be+    abstract because field duplication delegates its behavior to the `∧`+    operator++    This particular example fails because it desugars to:++        λ(r : { y : Natural }) → { x = { y = 1 } ∧ r }++    ... and the `∧` operator can infer that the two records collide on the+    field `y`+-}+λ(r : { y : Natural }) → { x = { y = 1 }, x = r }
+ dhall-lang/tests/type-inference/failure/unit/RecordLitDuplicateFieldsCollidingRecords.dhall view
@@ -0,0 +1,8 @@+{-  This fails because the expression desugars to:++        { x = { y = 0 } ∧ { y = 0 } }++    ... which is ill-typed due to `∧` forbidding collisions and the two `y`+    fields collide.+-}+{ x = { y = 0 }, x = { y = 0 } }
+ dhall-lang/tests/type-inference/failure/unit/RecordLitDuplicateFieldsNotRecords.dhall view
@@ -0,0 +1,7 @@+{-  This fails because the expression desugars to:++    { x = 0 ∧ 0 }++    ... which is ill-typed due to ∧ only working on records+-}+{ x = 0, x = 0 }
+ dhall-lang/tests/type-inference/failure/unit/RecordProjectionByTypeFieldTypeMismatch.dhall view
@@ -0,0 +1,1 @@+{ y = {=} }.( {y : Natural} )
+ dhall-lang/tests/type-inference/failure/unit/RecordProjectionByTypeNotPresent.dhall view
@@ -0,0 +1,1 @@+{ y = {=} }.( {x : Natural} )
+ dhall-lang/tests/type-inference/failure/unit/RecordProjectionDuplicateFields.dhall view
@@ -0,0 +1,1 @@+{ x = 1 }.{ x, x }
+ dhall-lang/tests/type-inference/failure/unit/RecordProjectionEmpty.dhall view
@@ -0,0 +1,1 @@+{=}.{ x }
+ dhall-lang/tests/type-inference/failure/unit/RecordProjectionNotPresent.dhall view
@@ -0,0 +1,1 @@+{ y = {=} }.{ x }
+ dhall-lang/tests/type-inference/failure/unit/RecordProjectionNotRecord.dhall view
@@ -0,0 +1,1 @@+True.{ x }
+ dhall-lang/tests/type-inference/failure/unit/RecordSelectionEmpty.dhall view
@@ -0,0 +1,1 @@+{=}.x
+ dhall-lang/tests/type-inference/failure/unit/RecordSelectionNotPresent.dhall view
@@ -0,0 +1,1 @@+{ y = {=} }.x
+ dhall-lang/tests/type-inference/failure/unit/RecordSelectionNotRecord.dhall view
@@ -0,0 +1,1 @@+True.x
+ dhall-lang/tests/type-inference/failure/unit/RecordSelectionTypeNotUnionType.dhall view
@@ -0,0 +1,1 @@+Bool.x
+ dhall-lang/tests/type-inference/failure/unit/RecordTypeDuplicateFields.dhall view
@@ -0,0 +1,1 @@+{ x: Natural, x: Natural }
+ dhall-lang/tests/type-inference/failure/unit/RecordTypeValueMember.dhall view
@@ -0,0 +1,1 @@+{ x : True }
+ dhall-lang/tests/type-inference/failure/unit/RecursiveRecordMergeLhsNotRecord.dhall view
@@ -0,0 +1,1 @@+True ∧ {=}
+ dhall-lang/tests/type-inference/failure/unit/RecursiveRecordMergeOverlapping.dhall view
@@ -0,0 +1,1 @@+{ x = True } ∧ { x = False }
+ dhall-lang/tests/type-inference/failure/unit/RecursiveRecordMergeRhsNotRecord.dhall view
@@ -0,0 +1,1 @@+{=} ∧ True
+ dhall-lang/tests/type-inference/failure/unit/RecursiveRecordTypeMergeLhsNotRecordType.dhall view
@@ -0,0 +1,1 @@+Bool ⩓ {}
+ dhall-lang/tests/type-inference/failure/unit/RecursiveRecordTypeMergeOverlapping.dhall view
@@ -0,0 +1,1 @@+{ x : Bool } ⩓ { x : Natural }
+ dhall-lang/tests/type-inference/failure/unit/RecursiveRecordTypeMergeRhsNotRecordType.dhall view
@@ -0,0 +1,1 @@+{} ⩓ Bool
+ dhall-lang/tests/type-inference/failure/unit/RemovedBuiltinOptionalBuild.dhall view
@@ -0,0 +1,1 @@+Optional/build
+ dhall-lang/tests/type-inference/failure/unit/RemovedBuiltinOptionalFold.dhall view
@@ -0,0 +1,1 @@+Optional/fold
+ dhall-lang/tests/type-inference/failure/unit/RightBiasedRecordMergeLhsNotRecord.dhall view
@@ -0,0 +1,1 @@+True ⫽ {=}
+ dhall-lang/tests/type-inference/failure/unit/RightBiasedRecordMergeRhsNotRecord.dhall view
@@ -0,0 +1,1 @@+{=} ⫽ True
+ dhall-lang/tests/type-inference/failure/unit/ShowConstructorNotFullyApplied.dhall view
@@ -0,0 +1,1 @@+showConstructor < A : Bool >.A
+ dhall-lang/tests/type-inference/failure/unit/ShowConstructorNotFullyAppliedOptional.dhall view
@@ -0,0 +1,1 @@+showConstructor None
+ dhall-lang/tests/type-inference/failure/unit/ShowConstructorWrongArgument.dhall view
@@ -0,0 +1,1 @@+showConstructor 0
+ dhall-lang/tests/type-inference/failure/unit/SomeNotType.dhall view
@@ -0,0 +1,1 @@+Some Bool
+ dhall-lang/tests/type-inference/failure/unit/Sort.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/type-inference/failure/unit/TextLiteralInterpolateNotText.dhall view
@@ -0,0 +1,1 @@+"${1}"
+ dhall-lang/tests/type-inference/failure/unit/ToMapEmptyInvalidAnnotation.dhall view
@@ -0,0 +1,2 @@+-- The mapKey must be Text+toMap {=} : List { mapKey : Bool, mapValue : Text }
+ dhall-lang/tests/type-inference/failure/unit/ToMapWrongKind.dhall view
@@ -0,0 +1,1 @@+toMap { x = Bool }
+ dhall-lang/tests/type-inference/failure/unit/TypeAnnotationWrong.dhall view
@@ -0,0 +1,1 @@+1 : Bool
+ dhall-lang/tests/type-inference/failure/unit/UnionConstructorFieldNotPresent.dhall view
@@ -0,0 +1,1 @@+< x : Bool >.y
+ dhall-lang/tests/type-inference/failure/unit/UnionDeprecatedConstructorsKeyword.dhall view
@@ -0,0 +1,1 @@+constructors < Left : Natural | Right : Bool >
+ dhall-lang/tests/type-inference/failure/unit/UnionTypeDuplicateVariants1.dhall view
@@ -0,0 +1,1 @@+<x | x>
+ dhall-lang/tests/type-inference/failure/unit/UnionTypeDuplicateVariants2.dhall view
@@ -0,0 +1,1 @@+<x | x: Natural>
+ dhall-lang/tests/type-inference/failure/unit/UnionTypeNotType.dhall view
@@ -0,0 +1,1 @@+< x : True >
+ dhall-lang/tests/type-inference/failure/unit/VariableFree.dhall view
@@ -0,0 +1,1 @@+x
+ dhall-lang/tests/type-inference/failure/unit/WithInfersKind.dhall view
@@ -0,0 +1,1 @@+Some ({=} with x = Bool)
+ dhall-lang/tests/type-inference/failure/unit/WithInvalidOverrideA.dhall view
@@ -0,0 +1,6 @@+{-  The `with` keyword cannot "descend" past a field that is not a record++    In the following example, the `a` field is not a record, therefore there is+    no possibility of adding or overriding `a` with an inner `b` field+-}+{ a = 1 } with a.b = 2
+ dhall-lang/tests/type-inference/failure/unit/WithNotOptional.dhall view
@@ -0,0 +1,1 @@+{ x = 0 } with ? = 1
+ dhall-lang/tests/type-inference/failure/unit/WithNotRecord.dhall view
@@ -0,0 +1,1 @@+5 with a = 10
+ dhall-lang/tests/type-inference/failure/unit/WithOptionalRecordTypeChanged.dhall view
@@ -0,0 +1,1 @@+(None { x : Natural }) with ?.x = True
+ dhall-lang/tests/type-inference/failure/unit/WithOptionalTypeChanged.dhall view
@@ -0,0 +1,1 @@+(None Natural) with ? = "hello"
+ dhall-lang/tests/type-inference/failure/unit/Z.dhall view
@@ -0,0 +1,4 @@+-- The purpose of this test is to check that an implementation is not parsing a+-- standalone `Z` as a `TimeOffset`.  Instead, this should be treated as an+-- unbound variable named `Z`+Z
+ dhall-lang/tests/type-inference/success/CacheImportsA.dhall view
@@ -0,0 +1,11 @@+{-+	This URL returns (probably) a different result for each request. This test+	ensures that import results for a given URL are correctly cached within an+	execution of dhall.+-}+let _ =+		assert+	  :   https://test.dhall-lang.org/random-string as Text+		≡ https://test.dhall-lang.org/random-string as Text++in  0
+ dhall-lang/tests/type-inference/success/CacheImportsB.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/CacheImportsCanonicalizeA.dhall view
@@ -0,0 +1,10 @@+{-+	This URL returns (probably) a different result for each request. This test+	ensures that import locations are canonicalized before being cached.+-}+let _ =+		assert+	  :   https://test.dhall-lang.org/random-string as Text+		≡ https://test.dhall-lang.org/foo/../random-string as Text++in  0
+ dhall-lang/tests/type-inference/success/CacheImportsCanonicalizeB.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/accessEncodedTypeA.dhall view
@@ -0,0 +1,4 @@+  λ ( record+    : ∀(k : Kind) → ∀(makeRecord : ∀(x : Type) → ∀(y : Type → Type) → k) → k+    )+→ record Type (λ(x : Type) → λ(y : Type → Type) → x)
+ dhall-lang/tests/type-inference/success/accessEncodedTypeB.dhall view
@@ -0,0 +1,4 @@+  ∀ ( record+    : ∀(k : Kind) → ∀(makeRecord : ∀(x : Type) → ∀(y : Type → Type) → k) → k+    )+→ Type
+ dhall-lang/tests/type-inference/success/accessTypeA.dhall view
@@ -0,0 +1,1 @@+λ(record : { x : Type, y : Type → Type }) → record.x
+ dhall-lang/tests/type-inference/success/accessTypeB.dhall view
@@ -0,0 +1,1 @@+∀(record : { x : Type, y : Type → Type }) → Type
+ dhall-lang/tests/type-inference/success/preferMixedRecordsA.dhall view
@@ -0,0 +1,1 @@+{ foo = 1 } ⫽ { bar = Text }
+ dhall-lang/tests/type-inference/success/preferMixedRecordsB.dhall view
@@ -0,0 +1,1 @@+{ bar : Type, foo : Natural }
+ dhall-lang/tests/type-inference/success/preferMixedRecordsSameFieldA.dhall view
@@ -0,0 +1,1 @@+{ a = 0 } ⫽ { a = Bool }
+ dhall-lang/tests/type-inference/success/preferMixedRecordsSameFieldB.dhall view
@@ -0,0 +1,1 @@+{ a : Type }
+ dhall-lang/tests/type-inference/success/prelude/Bool/and/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/and.dhall [ True, False, True ]
+ dhall-lang/tests/type-inference/success/prelude/Bool/and/0B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Bool/and/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/and.dhall ([] : List Bool)
+ dhall-lang/tests/type-inference/success/prelude/Bool/and/1B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Bool/build/0A.dhall view
@@ -0,0 +1,2 @@+../../../../../../Prelude/Bool/build.dhall+(λ(bool : Type) → λ(true : bool) → λ(false : bool) → true)
+ dhall-lang/tests/type-inference/success/prelude/Bool/build/0B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Bool/build/1A.dhall view
@@ -0,0 +1,2 @@+../../../../../../Prelude/Bool/build.dhall+(λ(bool : Type) → λ(true : bool) → λ(false : bool) → false)
+ dhall-lang/tests/type-inference/success/prelude/Bool/build/1B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Bool/even/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/even.dhall [ False, True, False ]
+ dhall-lang/tests/type-inference/success/prelude/Bool/even/0B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Bool/even/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/even.dhall [ False, True ]
+ dhall-lang/tests/type-inference/success/prelude/Bool/even/1B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Bool/even/2A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/even.dhall [ False ]
+ dhall-lang/tests/type-inference/success/prelude/Bool/even/2B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Bool/even/3A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/even.dhall ([] : List Bool)
+ dhall-lang/tests/type-inference/success/prelude/Bool/even/3B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Bool/fold/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/fold.dhall True Natural 0 1
+ dhall-lang/tests/type-inference/success/prelude/Bool/fold/0B.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/prelude/Bool/fold/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/fold.dhall False Natural 0 1
+ dhall-lang/tests/type-inference/success/prelude/Bool/fold/1B.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/prelude/Bool/not/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/not.dhall True
+ dhall-lang/tests/type-inference/success/prelude/Bool/not/0B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Bool/not/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/not.dhall False
+ dhall-lang/tests/type-inference/success/prelude/Bool/not/1B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Bool/odd/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/odd.dhall [ True, False, True ]
+ dhall-lang/tests/type-inference/success/prelude/Bool/odd/0B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Bool/odd/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/odd.dhall [ True, False ]
+ dhall-lang/tests/type-inference/success/prelude/Bool/odd/1B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Bool/odd/2A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/odd.dhall [ True ]
+ dhall-lang/tests/type-inference/success/prelude/Bool/odd/2B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Bool/odd/3A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/odd.dhall ([] : List Bool)
+ dhall-lang/tests/type-inference/success/prelude/Bool/odd/3B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Bool/or/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/or.dhall [ True, False, True ]
+ dhall-lang/tests/type-inference/success/prelude/Bool/or/0B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Bool/or/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/or.dhall ([] : List Bool)
+ dhall-lang/tests/type-inference/success/prelude/Bool/or/1B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Bool/show/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/show.dhall True
+ dhall-lang/tests/type-inference/success/prelude/Bool/show/0B.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/prelude/Bool/show/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Bool/show.dhall False
+ dhall-lang/tests/type-inference/success/prelude/Bool/show/1B.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/prelude/Double/show/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Double/show.dhall -3.1
+ dhall-lang/tests/type-inference/success/prelude/Double/show/0B.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/prelude/Double/show/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Double/show.dhall 0.4
+ dhall-lang/tests/type-inference/success/prelude/Double/show/1B.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/prelude/Integer/show/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Integer/show.dhall -3
+ dhall-lang/tests/type-inference/success/prelude/Integer/show/0B.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/prelude/Integer/show/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Integer/show.dhall +0
+ dhall-lang/tests/type-inference/success/prelude/Integer/show/1B.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/prelude/Integer/toDouble/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Integer/toDouble.dhall -3
+ dhall-lang/tests/type-inference/success/prelude/Integer/toDouble/0B.dhall view
@@ -0,0 +1,1 @@+Double
+ dhall-lang/tests/type-inference/success/prelude/Integer/toDouble/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Integer/toDouble.dhall +2
+ dhall-lang/tests/type-inference/success/prelude/Integer/toDouble/1B.dhall view
@@ -0,0 +1,1 @@+Double
+ dhall-lang/tests/type-inference/success/prelude/List/all/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/all.dhall Natural Natural/even [ 2, 3, 5 ]
+ dhall-lang/tests/type-inference/success/prelude/List/all/0B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/List/all/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/all.dhall Natural Natural/even ([] : List Natural)
+ dhall-lang/tests/type-inference/success/prelude/List/all/1B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/List/any/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/any.dhall Natural Natural/even [ 2, 3, 5 ]
+ dhall-lang/tests/type-inference/success/prelude/List/any/0B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/List/any/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/any.dhall Natural Natural/even ([] : List Natural)
+ dhall-lang/tests/type-inference/success/prelude/List/any/1B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/List/build/0A.dhall view
@@ -0,0 +1,7 @@+../../../../../../Prelude/List/build.dhall+Text+( λ(list : Type)+→ λ(cons : Text → list → list)+→ λ(nil : list)+→ cons "ABC" (cons "DEF" nil)+)
+ dhall-lang/tests/type-inference/success/prelude/List/build/0B.dhall view
@@ -0,0 +1,1 @@+List Text
+ dhall-lang/tests/type-inference/success/prelude/List/build/1A.dhall view
@@ -0,0 +1,7 @@+../../../../../../Prelude/List/build.dhall+Text+( λ(list : Type)+→ λ(cons : Text → list → list)+→ λ(nil : list)+→ nil+)
+ dhall-lang/tests/type-inference/success/prelude/List/build/1B.dhall view
@@ -0,0 +1,1 @@+List Text
+ dhall-lang/tests/type-inference/success/prelude/List/concat/0A.dhall view
@@ -0,0 +1,5 @@+../../../../../../Prelude/List/concat.dhall Natural+[ [ 0, 1, 2 ]+, [ 3, 4 ]+, [ 5, 6, 7, 8 ]+]
+ dhall-lang/tests/type-inference/success/prelude/List/concat/0B.dhall view
@@ -0,0 +1,1 @@+List Natural
+ dhall-lang/tests/type-inference/success/prelude/List/concat/1A.dhall view
@@ -0,0 +1,5 @@+../../../../../../Prelude/List/concat.dhall Natural+[ [] : List Natural+, [] : List Natural+, [] : List Natural+]
+ dhall-lang/tests/type-inference/success/prelude/List/concat/1B.dhall view
@@ -0,0 +1,1 @@+List Natural
+ dhall-lang/tests/type-inference/success/prelude/List/concatMap/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/concatMap.dhall Natural Natural (λ(n : Natural) → [ n, n ]) [ 2, 3, 5 ]
+ dhall-lang/tests/type-inference/success/prelude/List/concatMap/0B.dhall view
@@ -0,0 +1,1 @@+List Natural
+ dhall-lang/tests/type-inference/success/prelude/List/concatMap/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/concatMap.dhall Natural Natural (λ(n : Natural) → [ n, n ]) ([] : List Natural)
+ dhall-lang/tests/type-inference/success/prelude/List/concatMap/1B.dhall view
@@ -0,0 +1,1 @@+List Natural
+ dhall-lang/tests/type-inference/success/prelude/List/filter/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/filter.dhall Natural Natural/even [ 2, 3, 5 ]
+ dhall-lang/tests/type-inference/success/prelude/List/filter/0B.dhall view
@@ -0,0 +1,1 @@+List Natural
+ dhall-lang/tests/type-inference/success/prelude/List/filter/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/filter.dhall Natural Natural/odd [ 2, 3, 5 ]
+ dhall-lang/tests/type-inference/success/prelude/List/filter/1B.dhall view
@@ -0,0 +1,1 @@+List Natural
+ dhall-lang/tests/type-inference/success/prelude/List/fold/0A.dhall view
@@ -0,0 +1,6 @@+../../../../../../Prelude/List/fold.dhall+Natural+[ 2, 3, 5 ]+Natural+(λ(x : Natural) → λ(y : Natural) → x + y)+0
+ dhall-lang/tests/type-inference/success/prelude/List/fold/0B.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/prelude/List/fold/1A.dhall view
@@ -0,0 +1,7 @@+  λ(nil : Natural)+→ ../../../../../../Prelude/List/fold.dhall+  Natural+  [ 2, 3, 5 ]+  Natural+  (λ(x : Natural) → λ(y : Natural) → x + y)+  nil
+ dhall-lang/tests/type-inference/success/prelude/List/fold/1B.dhall view
@@ -0,0 +1,1 @@+∀(nil : Natural) → Natural
+ dhall-lang/tests/type-inference/success/prelude/List/fold/2A.dhall view
@@ -0,0 +1,4 @@+  λ(list : Type)+→ λ(cons : Natural → list → list)+→ λ(nil : list)+→ ../../../../../../Prelude/List/fold.dhall Natural [ 2, 3, 5 ] list cons nil
+ dhall-lang/tests/type-inference/success/prelude/List/fold/2B.dhall view
@@ -0,0 +1,1 @@+∀(list : Type) → ∀(cons : Natural → list → list) → ∀(nil : list) → list
+ dhall-lang/tests/type-inference/success/prelude/List/generate/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/generate.dhall 5 Bool Natural/even
+ dhall-lang/tests/type-inference/success/prelude/List/generate/0B.dhall view
@@ -0,0 +1,1 @@+List Bool
+ dhall-lang/tests/type-inference/success/prelude/List/generate/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/generate.dhall 0 Bool Natural/even
+ dhall-lang/tests/type-inference/success/prelude/List/generate/1B.dhall view
@@ -0,0 +1,1 @@+List Bool
+ dhall-lang/tests/type-inference/success/prelude/List/head/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/head.dhall Natural [ 0, 1, 2 ]
+ dhall-lang/tests/type-inference/success/prelude/List/head/0B.dhall view
@@ -0,0 +1,1 @@+Optional Natural
+ dhall-lang/tests/type-inference/success/prelude/List/head/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/head.dhall Natural ([] : List Natural)
+ dhall-lang/tests/type-inference/success/prelude/List/head/1B.dhall view
@@ -0,0 +1,1 @@+Optional Natural
+ dhall-lang/tests/type-inference/success/prelude/List/indexed/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/indexed.dhall Bool [ True, False, True ]
+ dhall-lang/tests/type-inference/success/prelude/List/indexed/0B.dhall view
@@ -0,0 +1,1 @@+List { index : Natural, value : Bool }
+ dhall-lang/tests/type-inference/success/prelude/List/indexed/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/indexed.dhall Bool ([] : List Bool)
+ dhall-lang/tests/type-inference/success/prelude/List/indexed/1B.dhall view
@@ -0,0 +1,1 @@+List { index : Natural, value : Bool }
+ dhall-lang/tests/type-inference/success/prelude/List/iterate/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/iterate.dhall 10 Natural (λ(x : Natural) → x * 2) 1
+ dhall-lang/tests/type-inference/success/prelude/List/iterate/0B.dhall view
@@ -0,0 +1,1 @@+List Natural
+ dhall-lang/tests/type-inference/success/prelude/List/iterate/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/iterate.dhall 0 Natural (λ(x : Natural) → x * 2) 1
+ dhall-lang/tests/type-inference/success/prelude/List/iterate/1B.dhall view
@@ -0,0 +1,1 @@+List Natural
+ dhall-lang/tests/type-inference/success/prelude/List/last/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/last.dhall Natural [ 0, 1, 2 ]
+ dhall-lang/tests/type-inference/success/prelude/List/last/0B.dhall view
@@ -0,0 +1,1 @@+Optional Natural
+ dhall-lang/tests/type-inference/success/prelude/List/last/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/last.dhall Natural ([] : List Natural)
+ dhall-lang/tests/type-inference/success/prelude/List/last/1B.dhall view
@@ -0,0 +1,1 @@+Optional Natural
+ dhall-lang/tests/type-inference/success/prelude/List/length/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/length.dhall Natural [ 0, 1, 2 ]
+ dhall-lang/tests/type-inference/success/prelude/List/length/0B.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/prelude/List/length/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/length.dhall Natural ([] : List Natural)
+ dhall-lang/tests/type-inference/success/prelude/List/length/1B.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/prelude/List/map/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/map.dhall Natural Bool Natural/even [ 2, 3, 5 ]
+ dhall-lang/tests/type-inference/success/prelude/List/map/0B.dhall view
@@ -0,0 +1,1 @@+List Bool
+ dhall-lang/tests/type-inference/success/prelude/List/map/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/map.dhall Natural Bool Natural/even ([] : List Natural)
+ dhall-lang/tests/type-inference/success/prelude/List/map/1B.dhall view
@@ -0,0 +1,1 @@+List Bool
+ dhall-lang/tests/type-inference/success/prelude/List/null/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/null.dhall Natural [ 0, 1, 2 ]
+ dhall-lang/tests/type-inference/success/prelude/List/null/0B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/List/null/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/null.dhall Natural ([] : List Natural)
+ dhall-lang/tests/type-inference/success/prelude/List/null/1B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/List/replicate/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/replicate.dhall 9 Natural 1
+ dhall-lang/tests/type-inference/success/prelude/List/replicate/0B.dhall view
@@ -0,0 +1,1 @@+List Natural
+ dhall-lang/tests/type-inference/success/prelude/List/replicate/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/replicate.dhall 0 Natural 1
+ dhall-lang/tests/type-inference/success/prelude/List/replicate/1B.dhall view
@@ -0,0 +1,1 @@+List Natural
+ dhall-lang/tests/type-inference/success/prelude/List/reverse/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/reverse.dhall Natural [ 0, 1, 2 ]
+ dhall-lang/tests/type-inference/success/prelude/List/reverse/0B.dhall view
@@ -0,0 +1,1 @@+List Natural
+ dhall-lang/tests/type-inference/success/prelude/List/reverse/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/reverse.dhall Natural ([] : List Natural)
+ dhall-lang/tests/type-inference/success/prelude/List/reverse/1B.dhall view
@@ -0,0 +1,1 @@+List Natural
+ dhall-lang/tests/type-inference/success/prelude/List/shifted/0A.dhall view
@@ -0,0 +1,15 @@+../../../../../../Prelude/List/shifted.dhall+Bool+[ [ { index = 0, value = True }+  , { index = 1, value = True }+  , { index = 2, value = False }+  ]+, [ { index = 0, value = False }+  , { index = 1, value = False }+  ]+, [ { index = 0, value = True }+  , { index = 1, value = True }+  , { index = 2, value = True }+  , { index = 3, value = True }+  ]+]
+ dhall-lang/tests/type-inference/success/prelude/List/shifted/0B.dhall view
@@ -0,0 +1,1 @@+List { index : Natural, value : Bool }
+ dhall-lang/tests/type-inference/success/prelude/List/shifted/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/shifted.dhall Bool ([] : List (List { index : Natural, value : Bool }))
+ dhall-lang/tests/type-inference/success/prelude/List/shifted/1B.dhall view
@@ -0,0 +1,1 @@+List { index : Natural, value : Bool }
+ dhall-lang/tests/type-inference/success/prelude/List/unzip/0A.dhall view
@@ -0,0 +1,7 @@+../../../../../../Prelude/List/unzip.dhall+Text+Bool+[ { _1 = "ABC", _2 = True }+, { _1 = "DEF", _2 = False }+, { _1 = "GHI", _2 = True }+]
+ dhall-lang/tests/type-inference/success/prelude/List/unzip/0B.dhall view
@@ -0,0 +1,1 @@+{ _1 : List Text, _2 : List Bool }
+ dhall-lang/tests/type-inference/success/prelude/List/unzip/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/List/unzip.dhall Text Bool ([] : List { _1 : Text, _2 : Bool })
+ dhall-lang/tests/type-inference/success/prelude/List/unzip/1B.dhall view
@@ -0,0 +1,1 @@+{ _1 : List Text, _2 : List Bool }
+ dhall-lang/tests/type-inference/success/prelude/Monoid/00A.dhall view
@@ -0,0 +1,1 @@+../../../../../Prelude/Bool/and
+ dhall-lang/tests/type-inference/success/prelude/Monoid/00B.dhall view
@@ -0,0 +1,1 @@+∀(xs : List Bool) → Bool
+ dhall-lang/tests/type-inference/success/prelude/Monoid/01A.dhall view
@@ -0,0 +1,1 @@+../../../../../Prelude/Bool/or
+ dhall-lang/tests/type-inference/success/prelude/Monoid/01B.dhall view
@@ -0,0 +1,1 @@+∀(xs : List Bool) → Bool
+ dhall-lang/tests/type-inference/success/prelude/Monoid/02A.dhall view
@@ -0,0 +1,1 @@+../../../../../Prelude/Bool/even
+ dhall-lang/tests/type-inference/success/prelude/Monoid/02B.dhall view
@@ -0,0 +1,1 @@+∀(xs : List Bool) → Bool
+ dhall-lang/tests/type-inference/success/prelude/Monoid/03A.dhall view
@@ -0,0 +1,1 @@+../../../../../Prelude/Bool/odd
+ dhall-lang/tests/type-inference/success/prelude/Monoid/03B.dhall view
@@ -0,0 +1,1 @@+∀(xs : List Bool) → Bool
+ dhall-lang/tests/type-inference/success/prelude/Monoid/04A.dhall view
@@ -0,0 +1,1 @@+../../../../../Prelude/List/concat
+ dhall-lang/tests/type-inference/success/prelude/Monoid/04B.dhall view
@@ -0,0 +1,1 @@+∀(a : Type) → ∀(xss : List (List a)) → List a
+ dhall-lang/tests/type-inference/success/prelude/Monoid/05A.dhall view
@@ -0,0 +1,1 @@+../../../../../Prelude/List/shifted
+ dhall-lang/tests/type-inference/success/prelude/Monoid/05B.dhall view
@@ -0,0 +1,3 @@+  ∀(a : Type)+→ ∀(kvss : List (List { index : Natural, value : a }))+→ List { index : Natural, value : a }
+ dhall-lang/tests/type-inference/success/prelude/Monoid/06A.dhall view
@@ -0,0 +1,1 @@+../../../../../Prelude/Natural/sum
+ dhall-lang/tests/type-inference/success/prelude/Monoid/06B.dhall view
@@ -0,0 +1,1 @@+∀(xs : List Natural) → Natural
+ dhall-lang/tests/type-inference/success/prelude/Monoid/07A.dhall view
@@ -0,0 +1,1 @@+../../../../../Prelude/Natural/product
+ dhall-lang/tests/type-inference/success/prelude/Monoid/07B.dhall view
@@ -0,0 +1,1 @@+∀(xs : List Natural) → Natural
+ dhall-lang/tests/type-inference/success/prelude/Monoid/08A.dhall view
@@ -0,0 +1,1 @@+../../../../../Prelude/Optional/head
+ dhall-lang/tests/type-inference/success/prelude/Monoid/08B.dhall view
@@ -0,0 +1,1 @@+∀(a : Type) → ∀(xs : List (Optional a)) → Optional a
+ dhall-lang/tests/type-inference/success/prelude/Monoid/09A.dhall view
@@ -0,0 +1,1 @@+../../../../../Prelude/Optional/last
+ dhall-lang/tests/type-inference/success/prelude/Monoid/09B.dhall view
@@ -0,0 +1,1 @@+∀(a : Type) → ∀(xs : List (Optional a)) → Optional a
+ dhall-lang/tests/type-inference/success/prelude/Monoid/10A.dhall view
@@ -0,0 +1,1 @@+../../../../../Prelude/Text/concat
+ dhall-lang/tests/type-inference/success/prelude/Monoid/10B.dhall view
@@ -0,0 +1,1 @@+∀(xs : List Text) → Text
+ dhall-lang/tests/type-inference/success/prelude/Natural/build/0A.dhall view
@@ -0,0 +1,6 @@+../../../../../../Prelude/Natural/build.dhall+( λ(natural : Type)+→ λ(succ : natural → natural)+→ λ(zero : natural)+→ succ (succ (succ zero))+)
+ dhall-lang/tests/type-inference/success/prelude/Natural/build/0B.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/prelude/Natural/build/1A.dhall view
@@ -0,0 +1,6 @@+../../../../../../Prelude/Natural/build.dhall+( λ(natural : Type)+→ λ(succ : natural → natural)+→ λ(zero : natural)+→ zero+)
+ dhall-lang/tests/type-inference/success/prelude/Natural/build/1B.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/prelude/Natural/enumerate/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/enumerate.dhall 10
+ dhall-lang/tests/type-inference/success/prelude/Natural/enumerate/0B.dhall view
@@ -0,0 +1,1 @@+List Natural
+ dhall-lang/tests/type-inference/success/prelude/Natural/enumerate/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/enumerate.dhall 0
+ dhall-lang/tests/type-inference/success/prelude/Natural/enumerate/1B.dhall view
@@ -0,0 +1,1 @@+List Natural
+ dhall-lang/tests/type-inference/success/prelude/Natural/even/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/even.dhall 3
+ dhall-lang/tests/type-inference/success/prelude/Natural/even/0B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Natural/even/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/even.dhall 0
+ dhall-lang/tests/type-inference/success/prelude/Natural/even/1B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Natural/fold/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/fold.dhall 3 Natural (λ(x : Natural) → 5 * x) 1
+ dhall-lang/tests/type-inference/success/prelude/Natural/fold/0B.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/prelude/Natural/fold/1A.dhall view
@@ -0,0 +1,1 @@+λ(zero : Natural) → ../../../../../../Prelude/Natural/fold.dhall 3 Natural (λ(x : Natural) → 5 * x) zero
+ dhall-lang/tests/type-inference/success/prelude/Natural/fold/1B.dhall view
@@ -0,0 +1,1 @@+∀(zero : Natural) → Natural
+ dhall-lang/tests/type-inference/success/prelude/Natural/fold/2A.dhall view
@@ -0,0 +1,4 @@+  λ(natural : Type)+→ λ(succ : natural → natural)+→ λ(zero : natural)+→ ../../../../../../Prelude/Natural/fold.dhall 3 natural succ zero
+ dhall-lang/tests/type-inference/success/prelude/Natural/fold/2B.dhall view
@@ -0,0 +1,1 @@+∀(natural : Type) → ∀(succ : natural → natural) → ∀(zero : natural) → natural
+ dhall-lang/tests/type-inference/success/prelude/Natural/isZero/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/isZero.dhall 2
+ dhall-lang/tests/type-inference/success/prelude/Natural/isZero/0B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Natural/isZero/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/isZero.dhall 0
+ dhall-lang/tests/type-inference/success/prelude/Natural/isZero/1B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Natural/odd/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/odd.dhall 3
+ dhall-lang/tests/type-inference/success/prelude/Natural/odd/0B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Natural/odd/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/odd.dhall 0
+ dhall-lang/tests/type-inference/success/prelude/Natural/odd/1B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Natural/product/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/product.dhall [ 2, 3, 5 ]
+ dhall-lang/tests/type-inference/success/prelude/Natural/product/0B.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/prelude/Natural/product/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/product.dhall ([] : List Natural)
+ dhall-lang/tests/type-inference/success/prelude/Natural/product/1B.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/prelude/Natural/show/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/show.dhall 3
+ dhall-lang/tests/type-inference/success/prelude/Natural/show/0B.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/prelude/Natural/show/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/show.dhall 0
+ dhall-lang/tests/type-inference/success/prelude/Natural/show/1B.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/prelude/Natural/sum/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/sum.dhall [ 2, 3, 5 ]
+ dhall-lang/tests/type-inference/success/prelude/Natural/sum/0B.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/prelude/Natural/sum/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/sum.dhall ([] : List Natural)
+ dhall-lang/tests/type-inference/success/prelude/Natural/sum/1B.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/prelude/Natural/toDouble/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/toDouble.dhall 3
+ dhall-lang/tests/type-inference/success/prelude/Natural/toDouble/0B.dhall view
@@ -0,0 +1,1 @@+Double
+ dhall-lang/tests/type-inference/success/prelude/Natural/toDouble/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/toDouble.dhall 0
+ dhall-lang/tests/type-inference/success/prelude/Natural/toDouble/1B.dhall view
@@ -0,0 +1,1 @@+Double
+ dhall-lang/tests/type-inference/success/prelude/Natural/toInteger/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/toInteger.dhall 3
+ dhall-lang/tests/type-inference/success/prelude/Natural/toInteger/0B.dhall view
@@ -0,0 +1,1 @@+Integer
+ dhall-lang/tests/type-inference/success/prelude/Natural/toInteger/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Natural/toInteger.dhall 0
+ dhall-lang/tests/type-inference/success/prelude/Natural/toInteger/1B.dhall view
@@ -0,0 +1,1 @@+Integer
+ dhall-lang/tests/type-inference/success/prelude/Optional/all/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/all.dhall Natural Natural/even (Some 3)
+ dhall-lang/tests/type-inference/success/prelude/Optional/all/0B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Optional/all/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/all.dhall Natural Natural/even (None Natural)
+ dhall-lang/tests/type-inference/success/prelude/Optional/all/1B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Optional/any/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/any.dhall Natural Natural/even (Some 2)
+ dhall-lang/tests/type-inference/success/prelude/Optional/any/0B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Optional/any/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/any.dhall Natural Natural/even (None Natural)
+ dhall-lang/tests/type-inference/success/prelude/Optional/any/1B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Optional/build/0A.dhall view
@@ -0,0 +1,7 @@+../../../../../../Prelude/Optional/build.dhall+Natural+( λ(optional : Type)+→ λ(some : Natural → optional)+→ λ(none : optional)+→ some 1+)
+ dhall-lang/tests/type-inference/success/prelude/Optional/build/0B.dhall view
@@ -0,0 +1,1 @@+Optional Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/build/1A.dhall view
@@ -0,0 +1,7 @@+../../../../../../Prelude/Optional/build.dhall+Natural+( λ(optional : Type)+→ λ(some : Natural → optional)+→ λ(none : optional)+→ none+)
+ dhall-lang/tests/type-inference/success/prelude/Optional/build/1B.dhall view
@@ -0,0 +1,1 @@+Optional Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/concat/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/concat.dhall Natural (Some (Some 1))
+ dhall-lang/tests/type-inference/success/prelude/Optional/concat/0B.dhall view
@@ -0,0 +1,1 @@+Optional Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/concat/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/concat.dhall Natural (Some (None Natural))
+ dhall-lang/tests/type-inference/success/prelude/Optional/concat/1B.dhall view
@@ -0,0 +1,1 @@+Optional Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/concat/2A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/concat.dhall Natural (None (Optional Natural))
+ dhall-lang/tests/type-inference/success/prelude/Optional/concat/2B.dhall view
@@ -0,0 +1,1 @@+Optional Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/filter/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/filter.dhall Natural Natural/even (Some 2)
+ dhall-lang/tests/type-inference/success/prelude/Optional/filter/0B.dhall view
@@ -0,0 +1,1 @@+Optional Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/filter/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/filter.dhall Natural Natural/odd (Some 2)
+ dhall-lang/tests/type-inference/success/prelude/Optional/filter/1B.dhall view
@@ -0,0 +1,1 @@+Optional Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/fold/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/fold.dhall Natural (Some 2) Natural (λ(x : Natural) → x) 0
+ dhall-lang/tests/type-inference/success/prelude/Optional/fold/0B.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/fold/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/fold.dhall Natural (None Natural) Natural (λ(x : Natural) → x) 0
+ dhall-lang/tests/type-inference/success/prelude/Optional/fold/1B.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/head/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/head.dhall Natural [ None Natural, Some 1, Some 2 ]
+ dhall-lang/tests/type-inference/success/prelude/Optional/head/0B.dhall view
@@ -0,0 +1,1 @@+Optional Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/head/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/head.dhall Natural [ None Natural, None Natural ]
+ dhall-lang/tests/type-inference/success/prelude/Optional/head/1B.dhall view
@@ -0,0 +1,1 @@+Optional Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/head/2A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/head.dhall Natural ([] : List (Optional Natural))
+ dhall-lang/tests/type-inference/success/prelude/Optional/head/2B.dhall view
@@ -0,0 +1,1 @@+Optional Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/last/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/last.dhall Natural [ None Natural, Some 1, Some 2 ]
+ dhall-lang/tests/type-inference/success/prelude/Optional/last/0B.dhall view
@@ -0,0 +1,1 @@+Optional Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/last/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/last.dhall Natural [ None Natural, None Natural ]
+ dhall-lang/tests/type-inference/success/prelude/Optional/last/1B.dhall view
@@ -0,0 +1,1 @@+Optional Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/last/2A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/last.dhall Natural ([] : List (Optional Natural))
+ dhall-lang/tests/type-inference/success/prelude/Optional/last/2B.dhall view
@@ -0,0 +1,1 @@+Optional Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/length/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/length.dhall Natural (Some 2)
+ dhall-lang/tests/type-inference/success/prelude/Optional/length/0B.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/length/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/length.dhall Natural (None Natural)
+ dhall-lang/tests/type-inference/success/prelude/Optional/length/1B.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/map/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/map.dhall Natural Bool Natural/even (Some 3)
+ dhall-lang/tests/type-inference/success/prelude/Optional/map/0B.dhall view
@@ -0,0 +1,1 @@+Optional Bool
+ dhall-lang/tests/type-inference/success/prelude/Optional/map/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/map.dhall Natural Bool Natural/even (None Natural)
+ dhall-lang/tests/type-inference/success/prelude/Optional/map/1B.dhall view
@@ -0,0 +1,1 @@+Optional Bool
+ dhall-lang/tests/type-inference/success/prelude/Optional/null/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/null.dhall Natural (Some 2)
+ dhall-lang/tests/type-inference/success/prelude/Optional/null/0B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Optional/null/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/null.dhall Natural (None Natural)
+ dhall-lang/tests/type-inference/success/prelude/Optional/null/1B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/prelude/Optional/toList/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/toList.dhall Natural (Some 1)
+ dhall-lang/tests/type-inference/success/prelude/Optional/toList/0B.dhall view
@@ -0,0 +1,1 @@+List Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/toList/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/toList.dhall Natural (None Natural)
+ dhall-lang/tests/type-inference/success/prelude/Optional/toList/1B.dhall view
@@ -0,0 +1,1 @@+List Natural
+ dhall-lang/tests/type-inference/success/prelude/Optional/unzip/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/unzip.dhall Text Bool (Some { _1 = "ABC", _2 = True })
+ dhall-lang/tests/type-inference/success/prelude/Optional/unzip/0B.dhall view
@@ -0,0 +1,1 @@+{ _1 : Optional Text, _2 : Optional Bool }
+ dhall-lang/tests/type-inference/success/prelude/Optional/unzip/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Optional/unzip.dhall Text Bool (None { _1 : Text, _2 : Bool })
+ dhall-lang/tests/type-inference/success/prelude/Optional/unzip/1B.dhall view
@@ -0,0 +1,1 @@+{ _1 : Optional Text, _2 : Optional Bool }
+ dhall-lang/tests/type-inference/success/prelude/Text/concat/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Text/concat.dhall [ "ABC", "DEF", "GHI" ]
+ dhall-lang/tests/type-inference/success/prelude/Text/concat/0B.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/prelude/Text/concat/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Text/concat.dhall ([] : List Text)
+ dhall-lang/tests/type-inference/success/prelude/Text/concat/1B.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/prelude/Text/concatMap/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Text/concatMap.dhall Natural (λ(n : Natural) → "${Natural/show n} ") [ 0, 1, 2 ]
+ dhall-lang/tests/type-inference/success/prelude/Text/concatMap/0B.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/prelude/Text/concatMap/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Text/concatMap.dhall Natural (λ(n : Natural) → "${Natural/show n} ") ([] : List Natural)
+ dhall-lang/tests/type-inference/success/prelude/Text/concatMap/1B.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/prelude/Text/concatMapSep/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Text/concatMapSep.dhall ", " Natural Natural/show [ 0, 1, 2 ]
+ dhall-lang/tests/type-inference/success/prelude/Text/concatMapSep/0B.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/prelude/Text/concatMapSep/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Text/concatMapSep.dhall ", " Natural Natural/show ([] : List Natural)
+ dhall-lang/tests/type-inference/success/prelude/Text/concatMapSep/1B.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/prelude/Text/concatSep/0A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Text/concatSep.dhall ", " [ "ABC", "DEF", "GHI" ]
+ dhall-lang/tests/type-inference/success/prelude/Text/concatSep/0B.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/prelude/Text/concatSep/1A.dhall view
@@ -0,0 +1,1 @@+../../../../../../Prelude/Text/concatSep.dhall ", " ([] : List Text)
+ dhall-lang/tests/type-inference/success/prelude/Text/concatSep/1B.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/preludeA.dhall view
@@ -0,0 +1,1 @@+../../../Prelude/package.dhall
+ dhall-lang/tests/type-inference/success/preludeB.dhall view
@@ -0,0 +1,740 @@+{ Bool :+    { and : ∀(xs : List Bool) → Bool+    , build :+        ∀(f : ∀(bool : Type) → ∀(true : bool) → ∀(false : bool) → bool) → Bool+    , equal : ∀(x : Bool) → ∀(y : Bool) → Bool+    , even : ∀(xs : List Bool) → Bool+    , fold :+        ∀(b : Bool) → ∀(bool : Type) → ∀(true : bool) → ∀(false : bool) → bool+    , not : ∀(b : Bool) → Bool+    , odd : ∀(xs : List Bool) → Bool+    , or : ∀(xs : List Bool) → Bool+    , show : ∀(b : Bool) → Text+    }+, Date : { show : Date → Text }+, Double : { show : Double → Text }+, Function :+    { compose :+        ∀(a : Type) →+        ∀(b : Type) →+        ∀(c : Type) →+        ∀(f : a → b) →+        ∀(g : b → c) →+        ∀(x : a) →+          c+    , composeList : ∀(a : Type) → ∀(functions : List (a → a)) → a → a+    , identity : ∀(a : Type) → ∀(x : a) → a+    }+, Integer :+    { abs : ∀(n : Integer) → Natural+    , add : ∀(m : Integer) → ∀(n : Integer) → Integer+    , clamp : Integer → Natural+    , equal : ∀(a : Integer) → ∀(b : Integer) → Bool+    , greaterThan : ∀(x : Integer) → ∀(y : Integer) → Bool+    , greaterThanEqual : ∀(x : Integer) → ∀(y : Integer) → Bool+    , lessThan : ∀(x : Integer) → ∀(y : Integer) → Bool+    , lessThanEqual : ∀(x : Integer) → ∀(y : Integer) → Bool+    , multiply : ∀(m : Integer) → ∀(n : Integer) → Integer+    , negate : Integer → Integer+    , negative : ∀(n : Integer) → Bool+    , nonNegative : ∀(n : Integer) → Bool+    , nonPositive : ∀(n : Integer) → Bool+    , positive : ∀(n : Integer) → Bool+    , show : Integer → Text+    , subtract : ∀(m : Integer) → ∀(n : Integer) → Integer+    , toDouble : Integer → Double+    , toNatural : ∀(n : Integer) → Optional Natural+    }+, JSON :+    { Nesting : Type+    , Tagged : ∀(a : Type) → Type+    , Type : Type+    , array :+        ∀ ( x+          : List+              ( ∀(JSON : Type) →+                ∀ ( json+                  : { array : List JSON → JSON+                    , bool : Bool → JSON+                    , double : Double → JSON+                    , integer : Integer → JSON+                    , null : JSON+                    , object : List { mapKey : Text, mapValue : JSON } → JSON+                    , string : Text → JSON+                    }+                  ) →+                  JSON+              )+          ) →+        ∀(JSON : Type) →+        ∀ ( json+          : { array : List JSON → JSON+            , bool : Bool → JSON+            , double : Double → JSON+            , integer : Integer → JSON+            , null : JSON+            , object : List { mapKey : Text, mapValue : JSON } → JSON+            , string : Text → JSON+            }+          ) →+          JSON+    , bool :+        ∀(x : Bool) →+        ∀(JSON : Type) →+        ∀ ( json+          : { array : List JSON → JSON+            , bool : Bool → JSON+            , double : Double → JSON+            , integer : Integer → JSON+            , null : JSON+            , object : List { mapKey : Text, mapValue : JSON } → JSON+            , string : Text → JSON+            }+          ) →+          JSON+    , double :+        ∀(x : Double) →+        ∀(JSON : Type) →+        ∀ ( json+          : { array : List JSON → JSON+            , bool : Bool → JSON+            , double : Double → JSON+            , integer : Integer → JSON+            , null : JSON+            , object : List { mapKey : Text, mapValue : JSON } → JSON+            , string : Text → JSON+            }+          ) →+          JSON+    , integer :+        ∀(x : Integer) →+        ∀(JSON : Type) →+        ∀ ( json+          : { array : List JSON → JSON+            , bool : Bool → JSON+            , double : Double → JSON+            , integer : Integer → JSON+            , null : JSON+            , object : List { mapKey : Text, mapValue : JSON } → JSON+            , string : Text → JSON+            }+          ) →+          JSON+    , keyText :+        ∀(key : Text) → ∀(value : Text) → { mapKey : Text, mapValue : Text }+    , keyValue :+        ∀(v : Type) →+        ∀(key : Text) →+        ∀(value : v) →+          { mapKey : Text, mapValue : v }+    , natural :+        ∀(x : Natural) →+        ∀(JSON : Type) →+        ∀ ( json+          : { array : List JSON → JSON+            , bool : Bool → JSON+            , double : Double → JSON+            , integer : Integer → JSON+            , null : JSON+            , object : List { mapKey : Text, mapValue : JSON } → JSON+            , string : Text → JSON+            }+          ) →+          JSON+    , null :+        ∀(JSON : Type) →+        ∀ ( json+          : { array : List JSON → JSON+            , bool : Bool → JSON+            , double : Double → JSON+            , integer : Integer → JSON+            , null : JSON+            , object : List { mapKey : Text, mapValue : JSON } → JSON+            , string : Text → JSON+            }+          ) →+          JSON+    , number :+        ∀(x : Double) →+        ∀(JSON : Type) →+        ∀ ( json+          : { array : List JSON → JSON+            , bool : Bool → JSON+            , double : Double → JSON+            , integer : Integer → JSON+            , null : JSON+            , object : List { mapKey : Text, mapValue : JSON } → JSON+            , string : Text → JSON+            }+          ) →+          JSON+    , object :+        ∀ ( x+          : List+              { mapKey : Text+              , mapValue :+                  ∀(JSON : Type) →+                  ∀ ( json+                    : { array : List JSON → JSON+                      , bool : Bool → JSON+                      , double : Double → JSON+                      , integer : Integer → JSON+                      , null : JSON+                      , object : List { mapKey : Text, mapValue : JSON } → JSON+                      , string : Text → JSON+                      }+                    ) →+                    JSON+              }+          ) →+        ∀(JSON : Type) →+        ∀ ( json+          : { array : List JSON → JSON+            , bool : Bool → JSON+            , double : Double → JSON+            , integer : Integer → JSON+            , null : JSON+            , object : List { mapKey : Text, mapValue : JSON } → JSON+            , string : Text → JSON+            }+          ) →+          JSON+    , omitNullFields :+        ∀ ( old+          : ∀(JSON : Type) →+            ∀ ( json+              : { array : List JSON → JSON+                , bool : Bool → JSON+                , double : Double → JSON+                , integer : Integer → JSON+                , null : JSON+                , object : List { mapKey : Text, mapValue : JSON } → JSON+                , string : Text → JSON+                }+              ) →+              JSON+          ) →+        ∀(JSON : Type) →+        ∀ ( json+          : { array : List JSON → JSON+            , bool : Bool → JSON+            , double : Double → JSON+            , integer : Integer → JSON+            , null : JSON+            , object : List { mapKey : Text, mapValue : JSON } → JSON+            , string : Text → JSON+            }+          ) →+          JSON+    , render :+        ∀ ( json+          : ∀(JSON : Type) →+            ∀ ( json+              : { array : List JSON → JSON+                , bool : Bool → JSON+                , double : Double → JSON+                , integer : Integer → JSON+                , null : JSON+                , object : List { mapKey : Text, mapValue : JSON } → JSON+                , string : Text → JSON+                }+              ) →+              JSON+          ) →+          Text+    , renderCompact :+        ∀ ( j+          : ∀(JSON : Type) →+            ∀ ( json+              : { array : List JSON → JSON+                , bool : Bool → JSON+                , double : Double → JSON+                , integer : Integer → JSON+                , null : JSON+                , object : List { mapKey : Text, mapValue : JSON } → JSON+                , string : Text → JSON+                }+              ) →+              JSON+          ) →+          Text+    , renderInteger : ∀(integer : Integer) → Text+    , renderYAML :+        ∀ ( json+          : ∀(JSON : Type) →+            ∀ ( json+              : { array : List JSON → JSON+                , bool : Bool → JSON+                , double : Double → JSON+                , integer : Integer → JSON+                , null : JSON+                , object : List { mapKey : Text, mapValue : JSON } → JSON+                , string : Text → JSON+                }+              ) →+              JSON+          ) →+          Text+    , string :+        ∀(x : Text) →+        ∀(JSON : Type) →+        ∀ ( json+          : { array : List JSON → JSON+            , bool : Bool → JSON+            , double : Double → JSON+            , integer : Integer → JSON+            , null : JSON+            , object : List { mapKey : Text, mapValue : JSON } → JSON+            , string : Text → JSON+            }+          ) →+          JSON+    , tagInline :+        ∀(tagFieldName : Text) →+        ∀(a : Type) →+        ∀(contents : a) →+          { contents : a, field : Text, nesting : < Inline | Nested : Text > }+    , tagNested :+        ∀(contentsFieldName : Text) →+        ∀(tagFieldName : Text) →+        ∀(a : Type) →+        ∀(contents : a) →+          { contents : a, field : Text, nesting : < Inline | Nested : Text > }+    }+, List :+    { all : ∀(a : Type) → ∀(f : a → Bool) → ∀(xs : List a) → Bool+    , any : ∀(a : Type) → ∀(f : a → Bool) → ∀(xs : List a) → Bool+    , build :+        ∀(a : Type) →+        (∀(list : Type) → ∀(cons : a → list → list) → ∀(nil : list) → list) →+          List a+    , concat : ∀(a : Type) → ∀(xss : List (List a)) → List a+    , concatMap :+        ∀(a : Type) → ∀(b : Type) → ∀(f : a → List b) → ∀(xs : List a) → List b+    , default : ∀(a : Type) → ∀(o : Optional (List a)) → List a+    , drop : ∀(n : Natural) → ∀(a : Type) → ∀(xs : List a) → List a+    , empty : ∀(a : Type) → List a+    , filter : ∀(a : Type) → ∀(f : a → Bool) → ∀(xs : List a) → List a+    , filterMap :+        ∀(a : Type) →+        ∀(b : Type) →+        ∀(f : a → Optional b) →+        ∀(xs : List a) →+          List b+    , fold :+        ∀(a : Type) →+        List a →+        ∀(list : Type) →+        ∀(cons : a → list → list) →+        ∀(nil : list) →+          list+    , foldLeft :+        ∀(a : Type) →+        ∀(xs : List a) →+        ∀(list : Type) →+        ∀(cons : list → a → list) →+        ∀(nil : list) →+          list+    , generate : ∀(n : Natural) → ∀(a : Type) → ∀(f : Natural → a) → List a+    , head : ∀(a : Type) → List a → Optional a+    , index : ∀(n : Natural) → ∀(a : Type) → ∀(xs : List a) → Optional a+    , indexed : ∀(a : Type) → List a → List { index : Natural, value : a }+    , iterate : ∀(n : Natural) → ∀(a : Type) → ∀(f : a → a) → ∀(x : a) → List a+    , last : ∀(a : Type) → List a → Optional a+    , length : ∀(a : Type) → List a → Natural+    , map : ∀(a : Type) → ∀(b : Type) → ∀(f : a → b) → ∀(xs : List a) → List b+    , mapMaybe :+        ∀(a : Type) →+        ∀(b : Type) →+        ∀(f : a → Optional b) →+        ∀(xs : List a) →+          List b+    , mapWithIndex :+        ∀(a : Type) →+        ∀(b : Type) →+        ∀(f : Natural → a → b) →+        ∀(xs : List a) →+          List b+    , null : ∀(a : Type) → ∀(xs : List a) → Bool+    , partition :+        ∀(a : Type) →+        ∀(f : a → Bool) →+        ∀(xs : List a) →+          { false : List a, true : List a }+    , replicate : ∀(n : Natural) → ∀(a : Type) → ∀(x : a) → List a+    , reverse : ∀(a : Type) → List a → List a+    , shifted :+        ∀(a : Type) →+        ∀(kvss : List (List { index : Natural, value : a })) →+          List { index : Natural, value : a }+    , take : ∀(n : Natural) → ∀(a : Type) → ∀(xs : List a) → List a+    , unpackOptionals : ∀(a : Type) → ∀(xs : List (Optional a)) → List a+    , unzip :+        ∀(a : Type) →+        ∀(b : Type) →+        ∀(xs : List { _1 : a, _2 : b }) →+          { _1 : List a, _2 : List b }+    , zip :+        ∀(a : Type) →+        ∀(xs : List a) →+        ∀(b : Type) →+        ∀(ys : List b) →+          List { _1 : a, _2 : b }+    }+, Location : { Type : Type }+, Map :+    { Entry : ∀(k : Type) → ∀(v : Type) → Type+    , Type : ∀(k : Type) → ∀(v : Type) → Type+    , empty : ∀(k : Type) → ∀(v : Type) → List { mapKey : k, mapValue : v }+    , keyText :+        ∀(key : Text) → ∀(value : Text) → { mapKey : Text, mapValue : Text }+    , keyValue :+        ∀(v : Type) →+        ∀(key : Text) →+        ∀(value : v) →+          { mapKey : Text, mapValue : v }+    , keys :+        ∀(k : Type) →+        ∀(v : Type) →+        ∀(xs : List { mapKey : k, mapValue : v }) →+          List k+    , map :+        ∀(k : Type) →+        ∀(a : Type) →+        ∀(b : Type) →+        ∀(f : a → b) →+        ∀(m : List { mapKey : k, mapValue : a }) →+          List { mapKey : k, mapValue : b }+    , mapMaybe :+        ∀(k : Type) →+        ∀(a : Type) →+        ∀(b : Type) →+        ∀(f : a → Optional b) →+        ∀(m : List { mapKey : k, mapValue : a }) →+          List { mapKey : k, mapValue : b }+    , unpackOptionals :+        ∀(k : Type) →+        ∀(v : Type) →+        ∀(xs : List { mapKey : k, mapValue : Optional v }) →+          List { mapKey : k, mapValue : v }+    , values :+        ∀(k : Type) →+        ∀(v : Type) →+        ∀(xs : List { mapKey : k, mapValue : v }) →+          List v+    }+, Monoid : ∀(m : Type) → Type+, Natural :+    { build :+        ( ∀(natural : Type) →+          ∀(succ : natural → natural) →+          ∀(zero : natural) →+            natural+        ) →+          Natural+    , enumerate : ∀(n : Natural) → List Natural+    , equal : ∀(a : Natural) → ∀(b : Natural) → Bool+    , even : Natural → Bool+    , fold :+        Natural →+        ∀(natural : Type) →+        ∀(succ : natural → natural) →+        ∀(zero : natural) →+          natural+    , greaterThan : ∀(x : Natural) → ∀(y : Natural) → Bool+    , greaterThanEqual : ∀(x : Natural) → ∀(y : Natural) → Bool+    , isZero : Natural → Bool+    , lessThan : ∀(x : Natural) → ∀(y : Natural) → Bool+    , lessThanEqual : ∀(x : Natural) → ∀(y : Natural) → Bool+    , listMax : ∀(xs : List Natural) → Optional Natural+    , listMin : ∀(xs : List Natural) → Optional Natural+    , max : ∀(a : Natural) → ∀(b : Natural) → Natural+    , min : ∀(a : Natural) → ∀(b : Natural) → Natural+    , odd : Natural → Bool+    , product : ∀(xs : List Natural) → Natural+    , show : Natural → Text+    , sort : ∀(xs : List Natural) → List Natural+    , subtract : Natural → Natural → Natural+    , sum : ∀(xs : List Natural) → Natural+    , toDouble : ∀(n : Natural) → Double+    , toInteger : Natural → Integer+    }+, NonEmpty :+    { Type : ∀(a : Type) → Type+    , all :+        ∀(a : Type) →+        ∀(f : a → Bool) →+        ∀(xs : { head : a, tail : List a }) →+          Bool+    , any :+        ∀(a : Type) →+        ∀(f : a → Bool) →+        ∀(xs : { head : a, tail : List a }) →+          Bool+    , concat :+        ∀(a : Type) →+        ∀ ( xss+          : { head : { head : a, tail : List a }+            , tail : List { head : a, tail : List a }+            }+          ) →+          { head : a, tail : List a }+    , concatMap :+        ∀(a : Type) →+        ∀(b : Type) →+        ∀(f : a → { head : b, tail : List b }) →+        ∀(xs : { head : a, tail : List a }) →+          { head : b, tail : List b }+    , head : ∀(a : Type) → ∀(xs : { head : a, tail : List a }) → a+    , index :+        ∀(n : Natural) →+        ∀(a : Type) →+        ∀(xs : { head : a, tail : List a }) →+          Optional a+    , indexed :+        ∀(a : Type) →+        ∀(xs : { head : a, tail : List a }) →+          { head : { index : Natural, value : a }+          , tail : List { index : Natural, value : a }+          }+    , last : ∀(a : Type) → ∀(xs : { head : a, tail : List a }) → a+    , length : ∀(a : Type) → ∀(xs : { head : a, tail : List a }) → Natural+    , make :+        ∀(a : Type) →+        ∀(head : a) →+        ∀(tail : List a) →+          { head : a, tail : List a }+    , map :+        ∀(a : Type) →+        ∀(b : Type) →+        ∀(f : a → b) →+        ∀(xs : { head : a, tail : List a }) →+          { head : b, tail : List b }+    , reverse :+        ∀(a : Type) →+        ∀(xs : { head : a, tail : List a }) →+          { head : a, tail : List a }+    , shifted :+        ∀(a : Type) →+        ∀ ( kvss+          : { head :+                { head : { index : Natural, value : a }+                , tail : List { index : Natural, value : a }+                }+            , tail :+                List+                  { head : { index : Natural, value : a }+                  , tail : List { index : Natural, value : a }+                  }+            }+          ) →+          { head : { index : Natural, value : a }+          , tail : List { index : Natural, value : a }+          }+    , singleton : ∀(a : Type) → ∀(x : a) → { head : a, tail : List a }+    , toList : ∀(a : Type) → ∀(xs : { head : a, tail : List a }) → List a+    , unzip :+        ∀(a : Type) →+        ∀(b : Type) →+        ∀(xs : { head : { _1 : a, _2 : b }, tail : List { _1 : a, _2 : b } }) →+          { _1 : { head : a, tail : List a }, _2 : { head : b, tail : List b } }+    , zip :+        ∀(a : Type) →+        ∀(xs : { head : a, tail : List a }) →+        ∀(b : Type) →+        ∀(ys : { head : b, tail : List b }) →+          { head : { _1 : a, _2 : b }, tail : List { _1 : a, _2 : b } }+    }+, Operator :+    { `!=` : ∀(m : Bool) → ∀(n : Bool) → Bool+    , `#` : ∀(type : Type) → ∀(m : List type) → ∀(n : List type) → List type+    , `&&` : ∀(m : Bool) → ∀(n : Bool) → Bool+    , `*` : ∀(m : Natural) → ∀(n : Natural) → Natural+    , `+` : ∀(m : Natural) → ∀(n : Natural) → Natural+    , `++` : ∀(m : Text) → ∀(n : Text) → Text+    , `==` : ∀(m : Bool) → ∀(n : Bool) → Bool+    , `||` : ∀(m : Bool) → ∀(n : Bool) → Bool+    }+, Optional :+    { all : ∀(a : Type) → ∀(f : a → Bool) → ∀(xs : Optional a) → Bool+    , any : ∀(a : Type) → ∀(f : a → Bool) → ∀(xs : Optional a) → Bool+    , build :+        ∀(a : Type) →+        ∀ ( build+          : ∀(optional : Type) →+            ∀(some : a → optional) →+            ∀(none : optional) →+              optional+          ) →+          Optional a+    , concat : ∀(a : Type) → ∀(x : Optional (Optional a)) → Optional a+    , concatMap :+        ∀(a : Type) →+        ∀(b : Type) →+        ∀(f : a → Optional b) →+        ∀(o : Optional a) →+          Optional b+    , default : ∀(a : Type) → ∀(default : a) → ∀(o : Optional a) → a+    , equal :+        ∀(a : Type) →+        ∀(compare : a → a → Bool) →+        ∀(ox : Optional a) →+        ∀(oy : Optional a) →+          Bool+    , filter : ∀(a : Type) → ∀(f : a → Bool) → ∀(xs : Optional a) → Optional a+    , fold :+        ∀(a : Type) →+        ∀(o : Optional a) →+        ∀(optional : Type) →+        ∀(some : a → optional) →+        ∀(none : optional) →+          optional+    , head : ∀(a : Type) → ∀(xs : List (Optional a)) → Optional a+    , last : ∀(a : Type) → ∀(xs : List (Optional a)) → Optional a+    , length : ∀(a : Type) → ∀(xs : Optional a) → Natural+    , map :+        ∀(a : Type) →+        ∀(b : Type) →+        ∀(f : a → b) →+        ∀(o : Optional a) →+          Optional b+    , null : ∀(a : Type) → ∀(xs : Optional a) → Bool+    , toList : ∀(a : Type) → ∀(o : Optional a) → List a+    , unzip :+        ∀(a : Type) →+        ∀(b : Type) →+        ∀(xs : Optional { _1 : a, _2 : b }) →+          { _1 : Optional a, _2 : Optional b }+    }+, Text :+    { concat : ∀(xs : List Text) → Text+    , concatMap : ∀(a : Type) → ∀(f : a → Text) → ∀(xs : List a) → Text+    , concatMapSep :+        ∀(separator : Text) →+        ∀(a : Type) →+        ∀(f : a → Text) →+        ∀(elements : List a) →+          Text+    , concatSep : ∀(separator : Text) → ∀(elements : List Text) → Text+    , default : ∀(o : Optional Text) → Text+    , defaultMap : ∀(a : Type) → ∀(f : a → Text) → ∀(o : Optional a) → Text+    , lowerASCII : ∀(nil : Text) → Text+    , replace :+        ∀(needle : Text) → ∀(replacement : Text) → ∀(haystack : Text) → Text+    , replicate : ∀(num : Natural) → ∀(text : Text) → Text+    , shell-escape : ∀(xs : Text) → Text+    , show : Text → Text+    , spaces : ∀(a : Natural) → Text+    , upperASCII : ∀(nil : Text) → Text+    }+, Time : { show : Time → Text }+, TimeZone : { show : TimeZone → Text }+, XML :+    { Type : Type+    , attribute :+        ∀(key : Text) → ∀(value : Text) → { mapKey : Text, mapValue : Text }+    , element :+        ∀ ( elem+          : { attributes : List { mapKey : Text, mapValue : Text }+            , content :+                List+                  ( ∀(XML : Type) →+                    ∀ ( xml+                      : { element :+                            { attributes :+                                List { mapKey : Text, mapValue : Text }+                            , content : List XML+                            , name : Text+                            } →+                              XML+                        , rawText : Text → XML+                        , text : Text → XML+                        }+                      ) →+                      XML+                  )+            , name : Text+            }+          ) →+        ∀(XML : Type) →+        ∀ ( xml+          : { element :+                { attributes : List { mapKey : Text, mapValue : Text }+                , content : List XML+                , name : Text+                } →+                  XML+            , rawText : Text → XML+            , text : Text → XML+            }+          ) →+          XML+    , emptyAttributes : List { mapKey : Text, mapValue : Text }+    , leaf :+        ∀ ( elem+          : { attributes : List { mapKey : Text, mapValue : Text }+            , name : Text+            }+          ) →+        ∀(XML : Type) →+        ∀ ( xml+          : { element :+                { attributes : List { mapKey : Text, mapValue : Text }+                , content : List XML+                , name : Text+                } →+                  XML+            , rawText : Text → XML+            , text : Text → XML+            }+          ) →+          XML+    , rawText :+        ∀(d : Text) →+        ∀(XML : Type) →+        ∀ ( xml+          : { element :+                { attributes : List { mapKey : Text, mapValue : Text }+                , content : List XML+                , name : Text+                } →+                  XML+            , rawText : Text → XML+            , text : Text → XML+            }+          ) →+          XML+    , render :+        ∀ ( x+          : ∀(XML : Type) →+            ∀ ( xml+              : { element :+                    { attributes : List { mapKey : Text, mapValue : Text }+                    , content : List XML+                    , name : Text+                    } →+                      XML+                , rawText : Text → XML+                , text : Text → XML+                }+              ) →+              XML+          ) →+          Text+    , text :+        ∀(d : Text) →+        ∀(XML : Type) →+        ∀ ( xml+          : { element :+                { attributes : List { mapKey : Text, mapValue : Text }+                , content : List XML+                , name : Text+                } →+                  XML+            , rawText : Text → XML+            , text : Text → XML+            }+          ) →+          XML+    }+}
+ dhall-lang/tests/type-inference/success/recordOfRecordOfTypesA.dhall view
@@ -0,0 +1,5 @@+let types = { Scopes = < Public | Private > }++let prelude = { types = types }++in  prelude.types.Scopes.Public
+ dhall-lang/tests/type-inference/success/recordOfRecordOfTypesB.dhall view
@@ -0,0 +1,1 @@+< Private | Public >
+ dhall-lang/tests/type-inference/success/recordOfTypesA.dhall view
@@ -0,0 +1,1 @@+{ x = Text, y = List }
+ dhall-lang/tests/type-inference/success/recordOfTypesB.dhall view
@@ -0,0 +1,1 @@+{ x : Type, y : Type → Type }
+ dhall-lang/tests/type-inference/success/regression/LambdaInLetScoping1A.dhall view
@@ -0,0 +1,1 @@+let T = 0 in λ(T : Type) → λ(x : T) → 1
+ dhall-lang/tests/type-inference/success/regression/LambdaInLetScoping1B.dhall view
@@ -0,0 +1,1 @@+∀(T : Type) → ∀(x : T) → Natural
+ dhall-lang/tests/type-inference/success/regression/LambdaInLetScoping2A.dhall view
@@ -0,0 +1,1 @@+(λ(T : Type) → let x = 0 in λ(x : T) → x) : ∀(T : Type) → ∀(x : T) → T
+ dhall-lang/tests/type-inference/success/regression/LambdaInLetScoping2B.dhall view
@@ -0,0 +1,1 @@+∀(T : Type) → ∀(x : T) → T
+ dhall-lang/tests/type-inference/success/regression/RecursiveRecordTypeMergeTripleCollisionA.dhall view
@@ -0,0 +1,1 @@+{ x : { a : Bool } } ⩓ { x : { b : Bool } } ⩓ { x : { c : Bool } }
+ dhall-lang/tests/type-inference/success/regression/RecursiveRecordTypeMergeTripleCollisionB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/regression/TodoA.dhall view
@@ -0,0 +1,1 @@+λ(todo : ∀(a : Type) → a) → todo
+ dhall-lang/tests/type-inference/success/regression/TodoB.dhall view
@@ -0,0 +1,1 @@+∀(todo : ∀(a : Type) → a) → ∀(a : Type) → a
+ dhall-lang/tests/type-inference/success/simple/access/0A.dhall view
@@ -0,0 +1,1 @@+{ x = Text }.x
+ dhall-lang/tests/type-inference/success/simple/access/0B.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/simple/access/1A.dhall view
@@ -0,0 +1,1 @@+< Foo : Text | Bar : Natural >.Foo
+ dhall-lang/tests/type-inference/success/simple/access/1B.dhall view
@@ -0,0 +1,1 @@+∀(Foo : Text) → < Bar : Natural | Foo : Text >
+ dhall-lang/tests/type-inference/success/simple/anonymousFunctionsInTypesA.dhall view
@@ -0,0 +1,5 @@+    let anonymousFunction = λ(a : Type) → List a++in    λ(HigherOrderType : (Type → Type) → Type)+    → λ(x : HigherOrderType anonymousFunction)+    → (x : HigherOrderType anonymousFunction)
+ dhall-lang/tests/type-inference/success/simple/anonymousFunctionsInTypesB.dhall view
@@ -0,0 +1,3 @@+  ∀(HigherOrderType : (Type → Type) → Type)+→ ∀(x : HigherOrderType (λ(a : Type) → List a))+→ HigherOrderType (λ(a : Type) → List a)
+ dhall-lang/tests/type-inference/success/simple/combineMixedRecordsA.dhall view
@@ -0,0 +1,1 @@+{ foo = 1 } ∧ { bar = Text }
+ dhall-lang/tests/type-inference/success/simple/combineMixedRecordsB.dhall view
@@ -0,0 +1,1 @@+{ bar : Type, foo : Natural }
+ dhall-lang/tests/type-inference/success/simple/completionA.dhall view
@@ -0,0 +1,25 @@+let Example =+      { Type = { name : Text, id : Optional Natural }+      , default = { name = "", id = None Natural }+      }++let ExtraFields = Example ∧ { extra = {=} }++let RequiredFields =+        { Type = { name : Text, id : Optional Natural }+        , default = { id = None Natural }+        }++let WrongDefaultType =+        { Type = { name : Text, id : Optional Natural }+        , default = { id = True }+        }++in  { example0 = Example::{=}+    , example1 = Example::{ name = "John Doe" }+    , example2 = Example::{ id = Some 0 }+    , example3 = Example::{ name = "Mary Jane", id = Some 0 }+    , example4 = ExtraFields::{=}+    , example5 = RequiredFields::{ name = "Jane Smith" }+    , example6 = WrongDefaultType::{ name = "Bob Roberts", id = Some 0 }+    }
+ dhall-lang/tests/type-inference/success/simple/completionB.dhall view
@@ -0,0 +1,8 @@+{ example0 : { id : Optional Natural, name : Text }+, example1 : { id : Optional Natural, name : Text }+, example2 : { id : Optional Natural, name : Text }+, example3 : { id : Optional Natural, name : Text }+, example4 : { id : Optional Natural, name : Text }+, example5 : { id : Optional Natural, name : Text }+, example6 : { id : Optional Natural, name : Text }+}
+ dhall-lang/tests/type-inference/success/simple/complexShadowingA.dhall view
@@ -0,0 +1,6 @@+let x = Bool+let x = Natural+in  \(x: x@1 {- Bool -})+ -> \(x: x@1 {- Natural -})+ -> let x = if x@1 then 0 else 1+    in  (x + x@1) : x@3
+ dhall-lang/tests/type-inference/success/simple/complexShadowingB.dhall view
@@ -0,0 +1,1 @@+∀(x : Bool) → ∀(x : Natural) → Natural
+ dhall-lang/tests/type-inference/success/simple/fieldsAreTypesA.dhall view
@@ -0,0 +1,1 @@+{ x = Bool, y = Text, z = List }
+ dhall-lang/tests/type-inference/success/simple/fieldsAreTypesB.dhall view
@@ -0,0 +1,1 @@+{ x : Type, y : Type, z : Type → Type }
+ dhall-lang/tests/type-inference/success/simple/kindParameterA.dhall view
@@ -0,0 +1,1 @@+λ(k : Kind) → λ(a : k → k → Type) → λ(x : k) → a x
+ dhall-lang/tests/type-inference/success/simple/kindParameterB.dhall view
@@ -0,0 +1,1 @@+∀(k : Kind) → ∀(a : k → k → Type) → ∀(x : k) → k → Type
+ dhall-lang/tests/type-inference/success/simple/mergeEquivalenceA.dhall view
@@ -0,0 +1,6 @@+let Foo = < Bar : Natural | Baz : Natural >++in    λ(a : Type)+	→ λ(f : Natural → a)+	→ λ(ts : Foo)+	→ merge { Bar = λ(a : Natural) → f a, Baz = f } ts
+ dhall-lang/tests/type-inference/success/simple/mergeEquivalenceB.dhall view
@@ -0,0 +1,1 @@+∀(a : Type) → ∀(f : Natural → a) → ∀(ts : < Bar : Natural | Baz : Natural >) → a
+ dhall-lang/tests/type-inference/success/simple/mixedFieldAccessA.dhall view
@@ -0,0 +1,9 @@+-- Verify that users can use `.` to both access a record field and a union+-- constructor within the same expression.  This is a common idiom if a user+-- provides a types package.++let Scope = < Public | Private >++let types = { Scope = Scope }++in  types.Scope.Public
+ dhall-lang/tests/type-inference/success/simple/mixedFieldAccessB.dhall view
@@ -0,0 +1,1 @@+< Private | Public >
+ dhall-lang/tests/type-inference/success/simple/orderInsensitivityA.dhall view
@@ -0,0 +1,15 @@+{- This test caught a regression in the Haskell implementation's typechecker.++   The typechecker was not sorting the fields of a record type inferred from a+   projection, meaning that it inferred that the fully normalized type of+   the subexpression `{ bar = "", foo = "" }.{ foo, bar }` was+   `{ foo : Text, bar : Text }` when according to the standard the inferred type+   should have been `{ bar : Text, foo : Text }`.  On top of that the Haskell+   implementation was sensitive to field order, leading to a type mismatch+   when applying a function whose input type had the fields sorted.++   This test ensures that implementations correctly handle order-insensitivity+   when projecting fields and/or comparing types, just in case they are+   order-sensitive like the Haskell implementation.+-}+λ(f : { bar : Text, foo : Text } → Bool) → f { bar = "", foo = "" }.{ foo, bar }
+ dhall-lang/tests/type-inference/success/simple/orderInsensitivityB.dhall view
@@ -0,0 +1,1 @@+∀(f : { bar : Text, foo : Text } → Bool) → Bool
+ dhall-lang/tests/type-inference/success/simple/toMapEmptyNormalizeAnnotationA.dhall view
@@ -0,0 +1,3 @@+toMap+  { x = Bool }.{}+: List { mapKey : { t = Text }.t, mapValue : { t = Double }.t }
+ dhall-lang/tests/type-inference/success/simple/toMapEmptyNormalizeAnnotationB.dhall view
@@ -0,0 +1,1 @@+List { mapKey : Text, mapValue : Double }
+ dhall-lang/tests/type-inference/success/simple/unionsOfTypesA.dhall view
@@ -0,0 +1,1 @@+< Left : Type → Type | Right : Type >.Left List
+ dhall-lang/tests/type-inference/success/simple/unionsOfTypesB.dhall view
@@ -0,0 +1,1 @@+< Left : Type → Type | Right : Type >
+ dhall-lang/tests/type-inference/success/unit/AssertAlphaA.dhall view
@@ -0,0 +1,1 @@+assert : (\(x: Bool) -> x) === (\(y: Bool) -> y)
+ dhall-lang/tests/type-inference/success/unit/AssertAlphaB.dhall view
@@ -0,0 +1,1 @@+(λ(x : Bool) → x) ≡ (λ(y : Bool) → y)
+ dhall-lang/tests/type-inference/success/unit/AssertNaNA.dhall view
@@ -0,0 +1,6 @@+{-+    Equivalence must compare the result of the binary encoding, so in+    particular comparing Doubles should not use standard float equality (where+    NaN != NaN).+-}+assert : NaN === NaN
+ dhall-lang/tests/type-inference/success/unit/AssertNaNB.dhall view
@@ -0,0 +1,1 @@+NaN ≡ NaN
+ dhall-lang/tests/type-inference/success/unit/AssertSimpleA.dhall view
@@ -0,0 +1,1 @@+assert : 1 + 1 === 2
+ dhall-lang/tests/type-inference/success/unit/AssertSimpleB.dhall view
@@ -0,0 +1,1 @@+2 ≡ 2
+ dhall-lang/tests/type-inference/success/unit/AssertTrivialA.dhall view
@@ -0,0 +1,1 @@+assert : 1 === 1
+ dhall-lang/tests/type-inference/success/unit/AssertTrivialB.dhall view
@@ -0,0 +1,1 @@+1 ≡ 1
+ dhall-lang/tests/type-inference/success/unit/BoolA.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/BoolB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/BytesLiteralA.dhall view
@@ -0,0 +1,1 @@+0x"0123456789abcdefABCDEF"
+ dhall-lang/tests/type-inference/success/unit/BytesLiteralB.dhall view
@@ -0,0 +1,1 @@+Bytes
+ dhall-lang/tests/type-inference/success/unit/CompletionA.dhall view
@@ -0,0 +1,1 @@+{ default = {=}, Type = {} }::{=}
+ dhall-lang/tests/type-inference/success/unit/CompletionB.dhall view
@@ -0,0 +1,1 @@+{}
+ dhall-lang/tests/type-inference/success/unit/ConstructorShiftA.dhall view
@@ -0,0 +1,1 @@+λ(t : Type) → < t : t >.t
+ dhall-lang/tests/type-inference/success/unit/ConstructorShiftB.dhall view
@@ -0,0 +1,1 @@+∀(t : Type) → ∀(t : t) → < t : t@1 >
+ dhall-lang/tests/type-inference/success/unit/DoubleA.dhall view
@@ -0,0 +1,1 @@+Double
+ dhall-lang/tests/type-inference/success/unit/DoubleB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/DoubleLiteralA.dhall view
@@ -0,0 +1,1 @@+1.0
+ dhall-lang/tests/type-inference/success/unit/DoubleLiteralB.dhall view
@@ -0,0 +1,1 @@+Double
+ dhall-lang/tests/type-inference/success/unit/DoubleShowA.dhall view
@@ -0,0 +1,1 @@+Double/show
+ dhall-lang/tests/type-inference/success/unit/DoubleShowB.dhall view
@@ -0,0 +1,1 @@+Double → Text
+ dhall-lang/tests/type-inference/success/unit/EquivalenceA.dhall view
@@ -0,0 +1,1 @@+1 === 2
+ dhall-lang/tests/type-inference/success/unit/EquivalenceB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/FalseA.dhall view
@@ -0,0 +1,1 @@+False
+ dhall-lang/tests/type-inference/success/unit/FalseB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/FunctionA.dhall view
@@ -0,0 +1,1 @@+λ(_ : Bool) → _
+ dhall-lang/tests/type-inference/success/unit/FunctionApplicationA.dhall view
@@ -0,0 +1,1 @@+(λ(_ : Bool) → _) True
+ dhall-lang/tests/type-inference/success/unit/FunctionApplicationB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/FunctionApplicationNormalizeArgumentA.dhall view
@@ -0,0 +1,1 @@+List/length (let x = 0 in Bool)
+ dhall-lang/tests/type-inference/success/unit/FunctionApplicationNormalizeArgumentB.dhall view
@@ -0,0 +1,1 @@+List Bool → Natural
+ dhall-lang/tests/type-inference/success/unit/FunctionApplicationNormalizeResultA.dhall view
@@ -0,0 +1,1 @@+(λ(g : Natural → Bool) → assert : g 0 ≡ g 0) Natural/even
+ dhall-lang/tests/type-inference/success/unit/FunctionApplicationNormalizeResultB.dhall view
@@ -0,0 +1,1 @@+True ≡ True
+ dhall-lang/tests/type-inference/success/unit/FunctionB.dhall view
@@ -0,0 +1,1 @@+Bool → Bool
+ dhall-lang/tests/type-inference/success/unit/FunctionDependentType1A.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → Bool
+ dhall-lang/tests/type-inference/success/unit/FunctionDependentType1B.dhall view
@@ -0,0 +1,1 @@+∀(x : Bool) → Type
+ dhall-lang/tests/type-inference/success/unit/FunctionDependentType2A.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → Type
+ dhall-lang/tests/type-inference/success/unit/FunctionDependentType2B.dhall view
@@ -0,0 +1,1 @@+∀(x : Bool) → Kind
+ dhall-lang/tests/type-inference/success/unit/FunctionNamedArgA.dhall view
@@ -0,0 +1,1 @@+λ(x : Bool) → x
+ dhall-lang/tests/type-inference/success/unit/FunctionNamedArgB.dhall view
@@ -0,0 +1,1 @@+∀(x : Bool) → Bool
+ dhall-lang/tests/type-inference/success/unit/FunctionNormalizeTypeAnnotationA.dhall view
@@ -0,0 +1,1 @@+λ(x : { t = Bool }.t) → x
+ dhall-lang/tests/type-inference/success/unit/FunctionNormalizeTypeAnnotationB.dhall view
@@ -0,0 +1,1 @@+∀(x : Bool) → Bool
+ dhall-lang/tests/type-inference/success/unit/FunctionTypeKindKindA.dhall view
@@ -0,0 +1,1 @@+Kind → Kind
+ dhall-lang/tests/type-inference/success/unit/FunctionTypeKindKindB.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/type-inference/success/unit/FunctionTypeKindTermA.dhall view
@@ -0,0 +1,1 @@+Kind → Bool
+ dhall-lang/tests/type-inference/success/unit/FunctionTypeKindTermB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/FunctionTypeKindTypeA.dhall view
@@ -0,0 +1,1 @@+Kind → Type
+ dhall-lang/tests/type-inference/success/unit/FunctionTypeKindTypeB.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/type-inference/success/unit/FunctionTypeTermTermA.dhall view
@@ -0,0 +1,1 @@+Bool → Bool
+ dhall-lang/tests/type-inference/success/unit/FunctionTypeTermTermB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/FunctionTypeTypeKindA.dhall view
@@ -0,0 +1,1 @@+Type → Kind
+ dhall-lang/tests/type-inference/success/unit/FunctionTypeTypeKindB.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/type-inference/success/unit/FunctionTypeTypeTermA.dhall view
@@ -0,0 +1,1 @@+Type → Bool
+ dhall-lang/tests/type-inference/success/unit/FunctionTypeTypeTermB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/FunctionTypeTypeTypeA.dhall view
@@ -0,0 +1,1 @@+Type → Type
+ dhall-lang/tests/type-inference/success/unit/FunctionTypeTypeTypeB.dhall view
@@ -0,0 +1,1 @@+Kind
+ dhall-lang/tests/type-inference/success/unit/FunctionTypeUsingArgumentA.dhall view
@@ -0,0 +1,1 @@+Type → _
+ dhall-lang/tests/type-inference/success/unit/FunctionTypeUsingArgumentB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/IfA.dhall view
@@ -0,0 +1,1 @@+if True then False else True
+ dhall-lang/tests/type-inference/success/unit/IfB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/IfBranchesKindA.dhall view
@@ -0,0 +1,1 @@+if True then (Type -> Type) else Type
+ dhall-lang/tests/type-inference/success/unit/IfBranchesKindB.dhall view
@@ -0,0 +1,1 @@+Kind
+ dhall-lang/tests/type-inference/success/unit/IfBranchesTypeA.dhall view
@@ -0,0 +1,1 @@+if True then Bool else Natural
+ dhall-lang/tests/type-inference/success/unit/IfBranchesTypeB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/IfNormalizeArgumentsA.dhall view
@@ -0,0 +1,9 @@+      if if True then True else True++then  if True then False else True++else  if True++then  True++else  True
+ dhall-lang/tests/type-inference/success/unit/IfNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/IntegerA.dhall view
@@ -0,0 +1,1 @@+Integer
+ dhall-lang/tests/type-inference/success/unit/IntegerB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/IntegerClampA.dhall view
@@ -0,0 +1,1 @@+Integer/clamp
+ dhall-lang/tests/type-inference/success/unit/IntegerClampB.dhall view
@@ -0,0 +1,1 @@+Integer → Natural
+ dhall-lang/tests/type-inference/success/unit/IntegerLiteralA.dhall view
@@ -0,0 +1,1 @@++1
+ dhall-lang/tests/type-inference/success/unit/IntegerLiteralB.dhall view
@@ -0,0 +1,1 @@+Integer
+ dhall-lang/tests/type-inference/success/unit/IntegerNegateA.dhall view
@@ -0,0 +1,1 @@+Integer/negate
+ dhall-lang/tests/type-inference/success/unit/IntegerNegateB.dhall view
@@ -0,0 +1,1 @@+Integer → Integer
+ dhall-lang/tests/type-inference/success/unit/IntegerShowA.dhall view
@@ -0,0 +1,1 @@+Integer/show
+ dhall-lang/tests/type-inference/success/unit/IntegerShowB.dhall view
@@ -0,0 +1,1 @@+Integer → Text
+ dhall-lang/tests/type-inference/success/unit/IntegerToDoubleA.dhall view
@@ -0,0 +1,1 @@+Integer/toDouble
+ dhall-lang/tests/type-inference/success/unit/IntegerToDoubleB.dhall view
@@ -0,0 +1,1 @@+Integer → Double
+ dhall-lang/tests/type-inference/success/unit/KindA.dhall view
@@ -0,0 +1,1 @@+Kind
+ dhall-lang/tests/type-inference/success/unit/KindB.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/type-inference/success/unit/LetA.dhall view
@@ -0,0 +1,1 @@+let x = True in x
+ dhall-lang/tests/type-inference/success/unit/LetB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/LetNestedTypeSynonymA.dhall view
@@ -0,0 +1,1 @@+let x = Bool let y : x = True in y
+ dhall-lang/tests/type-inference/success/unit/LetNestedTypeSynonymB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/LetTypeSynonymA.dhall view
@@ -0,0 +1,1 @@+let x = Bool in True : x
+ dhall-lang/tests/type-inference/success/unit/LetTypeSynonymB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/LetWithAnnotationA.dhall view
@@ -0,0 +1,1 @@+let x : Bool = True in x
+ dhall-lang/tests/type-inference/success/unit/LetWithAnnotationB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/ListA.dhall view
@@ -0,0 +1,1 @@+List
+ dhall-lang/tests/type-inference/success/unit/ListB.dhall view
@@ -0,0 +1,1 @@+Type → Type
+ dhall-lang/tests/type-inference/success/unit/ListBuildA.dhall view
@@ -0,0 +1,1 @@+List/build
+ dhall-lang/tests/type-inference/success/unit/ListBuildB.dhall view
@@ -0,0 +1,3 @@+  ∀(a : Type)+→ (∀(list : Type) → ∀(cons : a → list → list) → ∀(nil : list) → list)+→ List a
+ dhall-lang/tests/type-inference/success/unit/ListFoldA.dhall view
@@ -0,0 +1,1 @@+List/fold
+ dhall-lang/tests/type-inference/success/unit/ListFoldB.dhall view
@@ -0,0 +1,6 @@+  ∀(a : Type)+→ List a+→ ∀(list : Type)+→ ∀(cons : a → list → list)+→ ∀(nil : list)+→ list
+ dhall-lang/tests/type-inference/success/unit/ListHeadA.dhall view
@@ -0,0 +1,1 @@+List/head
+ dhall-lang/tests/type-inference/success/unit/ListHeadB.dhall view
@@ -0,0 +1,1 @@+∀(a : Type) → List a → Optional a
+ dhall-lang/tests/type-inference/success/unit/ListIndexedA.dhall view
@@ -0,0 +1,1 @@+List/indexed
+ dhall-lang/tests/type-inference/success/unit/ListIndexedB.dhall view
@@ -0,0 +1,1 @@+∀(a : Type) → List a → List { index : Natural, value : a }
+ dhall-lang/tests/type-inference/success/unit/ListLastA.dhall view
@@ -0,0 +1,1 @@+List/last
+ dhall-lang/tests/type-inference/success/unit/ListLastB.dhall view
@@ -0,0 +1,1 @@+∀(a : Type) → List a → Optional a
+ dhall-lang/tests/type-inference/success/unit/ListLengthA.dhall view
@@ -0,0 +1,1 @@+List/length
+ dhall-lang/tests/type-inference/success/unit/ListLengthB.dhall view
@@ -0,0 +1,1 @@+∀(a : Type) → List a → Natural
+ dhall-lang/tests/type-inference/success/unit/ListLiteralEmptyA.dhall view
@@ -0,0 +1,1 @@+[] : List Bool
+ dhall-lang/tests/type-inference/success/unit/ListLiteralEmptyB.dhall view
@@ -0,0 +1,1 @@+List Bool
+ dhall-lang/tests/type-inference/success/unit/ListLiteralEmptyNormalizeAnnotationA.dhall view
@@ -0,0 +1,1 @@+[] : { x = List Bool }.x
+ dhall-lang/tests/type-inference/success/unit/ListLiteralEmptyNormalizeAnnotationB.dhall view
@@ -0,0 +1,1 @@+List Bool
+ dhall-lang/tests/type-inference/success/unit/ListLiteralNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+[ if True then False else True ]
+ dhall-lang/tests/type-inference/success/unit/ListLiteralNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+List Bool
+ dhall-lang/tests/type-inference/success/unit/ListLiteralOneA.dhall view
@@ -0,0 +1,1 @@+[ True ]
+ dhall-lang/tests/type-inference/success/unit/ListLiteralOneB.dhall view
@@ -0,0 +1,1 @@+List Bool
+ dhall-lang/tests/type-inference/success/unit/ListReverseA.dhall view
@@ -0,0 +1,1 @@+List/reverse
+ dhall-lang/tests/type-inference/success/unit/ListReverseB.dhall view
@@ -0,0 +1,1 @@+∀(a : Type) → List a → List a
+ dhall-lang/tests/type-inference/success/unit/MergeEmptyAlternativeA.dhall view
@@ -0,0 +1,1 @@+merge { x = 1 } < x >.x
+ dhall-lang/tests/type-inference/success/unit/MergeEmptyAlternativeB.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/unit/MergeEmptyUnionA.dhall view
@@ -0,0 +1,1 @@+λ(x : <>) → merge {=} x : Bool
+ dhall-lang/tests/type-inference/success/unit/MergeEmptyUnionB.dhall view
@@ -0,0 +1,1 @@+∀(x : <>) → Bool
+ dhall-lang/tests/type-inference/success/unit/MergeNoneA.dhall view
@@ -0,0 +1,1 @@+merge { None = False, Some = \(b : Bool) -> b } (None Bool)
+ dhall-lang/tests/type-inference/success/unit/MergeNoneB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/MergeOneA.dhall view
@@ -0,0 +1,1 @@+merge { x = λ(_ : Bool) → _ } (< x : Bool >.x True)
+ dhall-lang/tests/type-inference/success/unit/MergeOneB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/MergeOneEmptyA.dhall view
@@ -0,0 +1,1 @@+merge { x = 5 } < x >.x
+ dhall-lang/tests/type-inference/success/unit/MergeOneEmptyB.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/unit/MergeOneWithAnnotation0A.dhall view
@@ -0,0 +1,1 @@+merge { x = λ(_ : Bool) → _ } (< x : Bool >.x True) : Bool
+ dhall-lang/tests/type-inference/success/unit/MergeOneWithAnnotation0B.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/MergeOneWithAnnotation1A.dhall view
@@ -0,0 +1,1 @@+merge { x = λ(y : Bool) → y } < x >.x : (∀(y : Bool) → Bool)
+ dhall-lang/tests/type-inference/success/unit/MergeOneWithAnnotation1B.dhall view
@@ -0,0 +1,1 @@+∀(y : Bool) → Bool
+ dhall-lang/tests/type-inference/success/unit/MergeOptionalA.dhall view
@@ -0,0 +1,1 @@+λ(x : Optional Bool) → merge { None = 0, Some = λ(_ : Bool) → 1 } x
+ dhall-lang/tests/type-inference/success/unit/MergeOptionalB.dhall view
@@ -0,0 +1,1 @@+∀(x : Optional Bool) → Natural
+ dhall-lang/tests/type-inference/success/unit/MergeSomeA.dhall view
@@ -0,0 +1,1 @@+merge { None = False, Some = \(b : Bool) -> b } (Some True)
+ dhall-lang/tests/type-inference/success/unit/MergeSomeB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/MergeTrickyShadowingA.dhall view
@@ -0,0 +1,1 @@+let _ = Bool in merge {_ = \(x: _) -> x} (<_: Bool>._ True)
+ dhall-lang/tests/type-inference/success/unit/MergeTrickyShadowingB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/NaturalA.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/unit/NaturalB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/NaturalBuildA.dhall view
@@ -0,0 +1,1 @@+Natural/build
+ dhall-lang/tests/type-inference/success/unit/NaturalBuildB.dhall view
@@ -0,0 +1,6 @@+  (   ∀(natural : Type)+    → ∀(succ : natural → natural)+    → ∀(zero : natural)+    → natural+  )+→ Natural
+ dhall-lang/tests/type-inference/success/unit/NaturalEvenA.dhall view
@@ -0,0 +1,1 @@+Natural/even
+ dhall-lang/tests/type-inference/success/unit/NaturalEvenB.dhall view
@@ -0,0 +1,1 @@+Natural → Bool
+ dhall-lang/tests/type-inference/success/unit/NaturalFoldA.dhall view
@@ -0,0 +1,1 @@+Natural/fold
+ dhall-lang/tests/type-inference/success/unit/NaturalFoldB.dhall view
@@ -0,0 +1,5 @@+  Natural+→ ∀(natural : Type)+→ ∀(succ : natural → natural)+→ ∀(zero : natural)+→ natural
+ dhall-lang/tests/type-inference/success/unit/NaturalIsZeroA.dhall view
@@ -0,0 +1,1 @@+Natural/isZero
+ dhall-lang/tests/type-inference/success/unit/NaturalIsZeroB.dhall view
@@ -0,0 +1,1 @@+Natural → Bool
+ dhall-lang/tests/type-inference/success/unit/NaturalLiteralA.dhall view
@@ -0,0 +1,1 @@+1
+ dhall-lang/tests/type-inference/success/unit/NaturalLiteralB.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/unit/NaturalOddA.dhall view
@@ -0,0 +1,1 @@+Natural/odd
+ dhall-lang/tests/type-inference/success/unit/NaturalOddB.dhall view
@@ -0,0 +1,1 @@+Natural → Bool
+ dhall-lang/tests/type-inference/success/unit/NaturalShowA.dhall view
@@ -0,0 +1,1 @@+Natural/show
+ dhall-lang/tests/type-inference/success/unit/NaturalShowB.dhall view
@@ -0,0 +1,1 @@+Natural → Text
+ dhall-lang/tests/type-inference/success/unit/NaturalSubtractA.dhall view
@@ -0,0 +1,1 @@+Natural/subtract
+ dhall-lang/tests/type-inference/success/unit/NaturalSubtractB.dhall view
@@ -0,0 +1,1 @@+Natural → Natural → Natural
+ dhall-lang/tests/type-inference/success/unit/NaturalToIntegerA.dhall view
@@ -0,0 +1,1 @@+Natural/toInteger
+ dhall-lang/tests/type-inference/success/unit/NaturalToIntegerB.dhall view
@@ -0,0 +1,1 @@+Natural → Integer
+ dhall-lang/tests/type-inference/success/unit/NoneA.dhall view
@@ -0,0 +1,1 @@+None
+ dhall-lang/tests/type-inference/success/unit/NoneB.dhall view
@@ -0,0 +1,1 @@+∀(A : Type) → Optional A
+ dhall-lang/tests/type-inference/success/unit/OperatorAndA.dhall view
@@ -0,0 +1,1 @@+True && False
+ dhall-lang/tests/type-inference/success/unit/OperatorAndB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/OperatorAndNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+True && False && False
+ dhall-lang/tests/type-inference/success/unit/OperatorAndNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/OperatorEqualA.dhall view
@@ -0,0 +1,1 @@+True == False
+ dhall-lang/tests/type-inference/success/unit/OperatorEqualB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/OperatorEqualNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+True == False == False
+ dhall-lang/tests/type-inference/success/unit/OperatorEqualNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/OperatorListConcatenateA.dhall view
@@ -0,0 +1,1 @@+[ True ] # [ True ]
+ dhall-lang/tests/type-inference/success/unit/OperatorListConcatenateB.dhall view
@@ -0,0 +1,1 @@+List Bool
+ dhall-lang/tests/type-inference/success/unit/OperatorListConcatenateNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+(if True then [ True ] else [ False ]) # (if True then [ True ] else [ False ])
+ dhall-lang/tests/type-inference/success/unit/OperatorListConcatenateNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+List Bool
+ dhall-lang/tests/type-inference/success/unit/OperatorNotEqualA.dhall view
@@ -0,0 +1,1 @@+True != False
+ dhall-lang/tests/type-inference/success/unit/OperatorNotEqualB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/OperatorNotEqualNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+True != False != False
+ dhall-lang/tests/type-inference/success/unit/OperatorNotEqualNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/OperatorOrA.dhall view
@@ -0,0 +1,1 @@+True || False
+ dhall-lang/tests/type-inference/success/unit/OperatorOrB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/OperatorOrNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+True || False || False
+ dhall-lang/tests/type-inference/success/unit/OperatorOrNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/OperatorPlusA.dhall view
@@ -0,0 +1,1 @@+1 + 1
+ dhall-lang/tests/type-inference/success/unit/OperatorPlusB.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/unit/OperatorPlusNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+1 + 1 + (1 + 1)
+ dhall-lang/tests/type-inference/success/unit/OperatorPlusNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/unit/OperatorTextConcatenateA.dhall view
@@ -0,0 +1,1 @@+"a" ++ "b"
+ dhall-lang/tests/type-inference/success/unit/OperatorTextConcatenateB.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/unit/OperatorTextConcatenateNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+"x" ++ "a" ++ ("y" ++ "b")
+ dhall-lang/tests/type-inference/success/unit/OperatorTextConcatenateNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/unit/OperatorTimesA.dhall view
@@ -0,0 +1,1 @@+1 * 1
+ dhall-lang/tests/type-inference/success/unit/OperatorTimesB.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/unit/OperatorTimesNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+1 * 1 * (1 * 1)
+ dhall-lang/tests/type-inference/success/unit/OperatorTimesNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+Natural
+ dhall-lang/tests/type-inference/success/unit/OptionalA.dhall view
@@ -0,0 +1,1 @@+Optional
+ dhall-lang/tests/type-inference/success/unit/OptionalB.dhall view
@@ -0,0 +1,1 @@+Type → Type
+ dhall-lang/tests/type-inference/success/unit/RecordEmptyA.dhall view
@@ -0,0 +1,1 @@+{=}
+ dhall-lang/tests/type-inference/success/unit/RecordEmptyB.dhall view
@@ -0,0 +1,1 @@+{}
+ dhall-lang/tests/type-inference/success/unit/RecordLitDottedFieldsA.dhall view
@@ -0,0 +1,1 @@+{ x.y.z = 1 }
+ dhall-lang/tests/type-inference/success/unit/RecordLitDottedFieldsB.dhall view
@@ -0,0 +1,1 @@+{ x : { y : { z : Natural } } }
+ dhall-lang/tests/type-inference/success/unit/RecordLitDottedFieldsMergeA.dhall view
@@ -0,0 +1,14 @@+{-  This example verifies that a Dhall interpreter correctly handles a corner+    case that other languages sometimes misbehave on++    The expression should desugar like this:++        λ(r : { z : Natural }) → { x.y = 1, x = r }++        λ(r : { z : Natural }) → { x = { y = 1 }, x = r }++        λ(r : { z : Natural }) → { x = { y = 1 } ∧ r }++    ... which type-checks since `{ y = 1 }` and `r` do not collide+-}+λ(r : { z : Natural }) → { x.y = 1, x = r }
+ dhall-lang/tests/type-inference/success/unit/RecordLitDottedFieldsMergeB.dhall view
@@ -0,0 +1,1 @@+∀(r : { z : Natural }) → { x : { y : Natural, z : Natural } }
+ dhall-lang/tests/type-inference/success/unit/RecordLitDuplicateFieldsAbstractA.dhall view
@@ -0,0 +1,12 @@+{-  This test illustrates that duplicate fields need not be literals in order+    to be properly normalized.  One or both of the duplicate fields can be+    abstract because field duplication delegates its behavior to the ∧ operator++    This particular example succeeds because it desugars to:++        λ(r : { z : Natural }) → { x = { y = 1 } ∧ r }++    ... and the `∧` operator can infer the absence of conflicts due to knowing+    the type of `r`+-}+λ(r : { z : Natural }) → { x = { y = 1 }, x = r }
+ dhall-lang/tests/type-inference/success/unit/RecordLitDuplicateFieldsAbstractB.dhall view
@@ -0,0 +1,1 @@+∀(r : { z : Natural }) → { x : { y : Natural, z : Natural } }
+ dhall-lang/tests/type-inference/success/unit/RecordLitDuplicateFieldsNoCollisionsA.dhall view
@@ -0,0 +1,12 @@+{-  This type-checks because the expression desugars to:++        { x = { y = 0 } ∧ { z = 0 } }++    ... which in turn type-checks due to the absence of a field collision.++    This expression is analogous to the following common Nix/TOML/Cue idiom,+    which we would like to support:++        { x.y = 0, x.z = 0 }+-}+{ x = { y = 0 }, x = { z = 0 } }
+ dhall-lang/tests/type-inference/success/unit/RecordLitDuplicateFieldsNoCollisionsB.dhall view
@@ -0,0 +1,1 @@+{ x : { y : Natural, z : Natural } }
+ dhall-lang/tests/type-inference/success/unit/RecordLitNormalizeFieldTypeA.dhall view
@@ -0,0 +1,1 @@+{ x = True : { t = Bool }.t }
+ dhall-lang/tests/type-inference/success/unit/RecordLitNormalizeFieldTypeB.dhall view
@@ -0,0 +1,1 @@+{ x : Bool }
+ dhall-lang/tests/type-inference/success/unit/RecordLitPunA.dhall view
@@ -0,0 +1,1 @@+\(x: Bool) -> { x }
+ dhall-lang/tests/type-inference/success/unit/RecordLitPunB.dhall view
@@ -0,0 +1,1 @@+∀(x : Bool) → { x : Bool }
+ dhall-lang/tests/type-inference/success/unit/RecordLitPunCaptureA.dhall view
@@ -0,0 +1,1 @@+\(x: Bool) -> \(x: Natural) -> { x }
+ dhall-lang/tests/type-inference/success/unit/RecordLitPunCaptureB.dhall view
@@ -0,0 +1,1 @@+∀(x : Bool) → ∀(x : Natural) → { x : Natural }
+ dhall-lang/tests/type-inference/success/unit/RecordLitPunSomeA.dhall view
@@ -0,0 +1,1 @@+let `None` = 0 let `Some` = \(_: Bool) -> 1 in { None, Some }
+ dhall-lang/tests/type-inference/success/unit/RecordLitPunSomeB.dhall view
@@ -0,0 +1,1 @@+{ None : Natural, Some : Bool → Natural }
+ dhall-lang/tests/type-inference/success/unit/RecordLitSortFieldsA.dhall view
@@ -0,0 +1,1 @@+{ b = 1, a = 2 }
+ dhall-lang/tests/type-inference/success/unit/RecordLitSortFieldsB.dhall view
@@ -0,0 +1,1 @@+{ a : Natural, b : Natural }
+ dhall-lang/tests/type-inference/success/unit/RecordMixedKinds2A.dhall view
@@ -0,0 +1,1 @@+{ x = Type, y = {} }
+ dhall-lang/tests/type-inference/success/unit/RecordMixedKinds2B.dhall view
@@ -0,0 +1,1 @@+{ x : Kind, y : Type }
+ dhall-lang/tests/type-inference/success/unit/RecordMixedKindsA.dhall view
@@ -0,0 +1,1 @@+{ x = {=}, y = Bool }
+ dhall-lang/tests/type-inference/success/unit/RecordMixedKindsB.dhall view
@@ -0,0 +1,1 @@+{ x : {}, y : Type }
+ dhall-lang/tests/type-inference/success/unit/RecordNestedKindA.dhall view
@@ -0,0 +1,1 @@+{ a = { b = Type } }
+ dhall-lang/tests/type-inference/success/unit/RecordNestedKindB.dhall view
@@ -0,0 +1,1 @@+{ a : { b : Kind } }
+ dhall-lang/tests/type-inference/success/unit/RecordNestedKindLikeA.dhall view
@@ -0,0 +1,1 @@+{ a = { b = Type → Type } }
+ dhall-lang/tests/type-inference/success/unit/RecordNestedKindLikeB.dhall view
@@ -0,0 +1,1 @@+{ a : { b : Kind } }
+ dhall-lang/tests/type-inference/success/unit/RecordNestedTypeA.dhall view
@@ -0,0 +1,1 @@+{ a = { b = Bool } }
+ dhall-lang/tests/type-inference/success/unit/RecordNestedTypeB.dhall view
@@ -0,0 +1,1 @@+{ a : { b : Type } }
+ dhall-lang/tests/type-inference/success/unit/RecordNestedTypeLikeA.dhall view
@@ -0,0 +1,1 @@+{ a = { b = Bool → Bool } }
+ dhall-lang/tests/type-inference/success/unit/RecordNestedTypeLikeB.dhall view
@@ -0,0 +1,1 @@+{ a : { b : Type } }
+ dhall-lang/tests/type-inference/success/unit/RecordOneKindA.dhall view
@@ -0,0 +1,1 @@+{ x = Type }
+ dhall-lang/tests/type-inference/success/unit/RecordOneKindB.dhall view
@@ -0,0 +1,1 @@+{ x : Kind }
+ dhall-lang/tests/type-inference/success/unit/RecordOneTypeA.dhall view
@@ -0,0 +1,1 @@+{ x = {} }
+ dhall-lang/tests/type-inference/success/unit/RecordOneTypeB.dhall view
@@ -0,0 +1,1 @@+{ x : Type }
+ dhall-lang/tests/type-inference/success/unit/RecordOneValueA.dhall view
@@ -0,0 +1,1 @@+{ x = {=} }
+ dhall-lang/tests/type-inference/success/unit/RecordOneValueB.dhall view
@@ -0,0 +1,1 @@+{ x : {} }
+ dhall-lang/tests/type-inference/success/unit/RecordProjectionByTypeA.dhall view
@@ -0,0 +1,1 @@+let e = { a = 10, b = "Text" } let s = { a : Natural } in e.(s)
+ dhall-lang/tests/type-inference/success/unit/RecordProjectionByTypeB.dhall view
@@ -0,0 +1,1 @@+{ a : Natural }
+ dhall-lang/tests/type-inference/success/unit/RecordProjectionByTypeEmptyA.dhall view
@@ -0,0 +1,1 @@+let e = { a = 10, b = "Text" } let s = { } in e.(s)
+ dhall-lang/tests/type-inference/success/unit/RecordProjectionByTypeEmptyB.dhall view
@@ -0,0 +1,1 @@+{}
+ dhall-lang/tests/type-inference/success/unit/RecordProjectionByTypeJudgmentalEqualityA.dhall view
@@ -0,0 +1,5 @@+-- This tests that we prefer the type from the selector over the inferred field+-- type from the record+-- ie the result should be `{ a : Natural → Natural }`+--                     not `{ a : ∀(x : Natural) → Natural }`+let e = { a = λ(x : Natural) → x } let s = { a : Natural → Natural } in e.(s)
+ dhall-lang/tests/type-inference/success/unit/RecordProjectionByTypeJudgmentalEqualityB.dhall view
@@ -0,0 +1,1 @@+{ a : Natural → Natural }
+ dhall-lang/tests/type-inference/success/unit/RecordProjectionEmptyA.dhall view
@@ -0,0 +1,1 @@+{ x = {=} }.{}
+ dhall-lang/tests/type-inference/success/unit/RecordProjectionEmptyB.dhall view
@@ -0,0 +1,1 @@+{}
+ dhall-lang/tests/type-inference/success/unit/RecordProjectionEmptyKindA.dhall view
@@ -0,0 +1,1 @@+{ x = Type }.{}
+ dhall-lang/tests/type-inference/success/unit/RecordProjectionEmptyKindB.dhall view
@@ -0,0 +1,1 @@+{}
+ dhall-lang/tests/type-inference/success/unit/RecordProjectionKindA.dhall view
@@ -0,0 +1,1 @@+{ x = Type, y = Type }.{ x }
+ dhall-lang/tests/type-inference/success/unit/RecordProjectionKindB.dhall view
@@ -0,0 +1,1 @@+{ x : Kind }
+ dhall-lang/tests/type-inference/success/unit/RecordProjectionTypeA.dhall view
@@ -0,0 +1,1 @@+{ x = Bool, y = Natural }.{ x }
+ dhall-lang/tests/type-inference/success/unit/RecordProjectionTypeB.dhall view
@@ -0,0 +1,1 @@+{ x : Type }
+ dhall-lang/tests/type-inference/success/unit/RecordProjectionValueA.dhall view
@@ -0,0 +1,1 @@+{ x = {=}, y = {=} }.{ x }
+ dhall-lang/tests/type-inference/success/unit/RecordProjectionValueB.dhall view
@@ -0,0 +1,1 @@+{ x : {} }
+ dhall-lang/tests/type-inference/success/unit/RecordSelectionKindA.dhall view
@@ -0,0 +1,1 @@+{ x = Type }.x
+ dhall-lang/tests/type-inference/success/unit/RecordSelectionKindB.dhall view
@@ -0,0 +1,1 @@+Kind
+ dhall-lang/tests/type-inference/success/unit/RecordSelectionTypeA.dhall view
@@ -0,0 +1,1 @@+{ x = {} }.x
+ dhall-lang/tests/type-inference/success/unit/RecordSelectionTypeB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/RecordSelectionValueA.dhall view
@@ -0,0 +1,1 @@+{ x = {=} }.x
+ dhall-lang/tests/type-inference/success/unit/RecordSelectionValueB.dhall view
@@ -0,0 +1,1 @@+{}
+ dhall-lang/tests/type-inference/success/unit/RecordTypeA.dhall view
@@ -0,0 +1,1 @@+{ x : Bool }
+ dhall-lang/tests/type-inference/success/unit/RecordTypeB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/RecordTypeEmptyA.dhall view
@@ -0,0 +1,1 @@+{}
+ dhall-lang/tests/type-inference/success/unit/RecordTypeEmptyB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/RecordTypeKindA.dhall view
@@ -0,0 +1,1 @@+{ x : Kind }
+ dhall-lang/tests/type-inference/success/unit/RecordTypeKindB.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/type-inference/success/unit/RecordTypeKindLikeA.dhall view
@@ -0,0 +1,1 @@+{ a : Kind → Kind }
+ dhall-lang/tests/type-inference/success/unit/RecordTypeKindLikeB.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/type-inference/success/unit/RecordTypeMixedKinds2A.dhall view
@@ -0,0 +1,1 @@+{ x : Kind, y : Type }
+ dhall-lang/tests/type-inference/success/unit/RecordTypeMixedKinds2B.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/type-inference/success/unit/RecordTypeMixedKinds3A.dhall view
@@ -0,0 +1,1 @@+{ x : Kind, y : Bool }
+ dhall-lang/tests/type-inference/success/unit/RecordTypeMixedKinds3B.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/type-inference/success/unit/RecordTypeMixedKindsA.dhall view
@@ -0,0 +1,1 @@+{ x : Bool, y : Type }
+ dhall-lang/tests/type-inference/success/unit/RecordTypeMixedKindsB.dhall view
@@ -0,0 +1,1 @@+Kind
+ dhall-lang/tests/type-inference/success/unit/RecordTypeNestedKindA.dhall view
@@ -0,0 +1,1 @@+{ a : { b : Kind } }
+ dhall-lang/tests/type-inference/success/unit/RecordTypeNestedKindB.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/type-inference/success/unit/RecordTypeNestedKindLikeA.dhall view
@@ -0,0 +1,1 @@+{ a : { b : Kind → Kind } }
+ dhall-lang/tests/type-inference/success/unit/RecordTypeNestedKindLikeB.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/type-inference/success/unit/RecordTypeTypeA.dhall view
@@ -0,0 +1,1 @@+{ x : Type }
+ dhall-lang/tests/type-inference/success/unit/RecordTypeTypeB.dhall view
@@ -0,0 +1,1 @@+Kind
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeBoolTypeA.dhall view
@@ -0,0 +1,1 @@+{ x : Bool } ⩓ { y : Type }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeBoolTypeB.dhall view
@@ -0,0 +1,1 @@+Kind
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeLhsEmptyA.dhall view
@@ -0,0 +1,1 @@+{=} ∧ { x = True }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeLhsEmptyB.dhall view
@@ -0,0 +1,1 @@+{ x : Bool }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeMixedKindsA.dhall view
@@ -0,0 +1,1 @@+{ x = True } ∧ { y = Bool }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeMixedKindsB.dhall view
@@ -0,0 +1,1 @@+{ x : Bool, y : Type }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeRecursivelyA.dhall view
@@ -0,0 +1,1 @@+{ x = { a = True } } ∧ { x = { b = True } }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeRecursivelyB.dhall view
@@ -0,0 +1,1 @@+{ x : { a : Bool, b : Bool } }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeRecursivelyKindsA.dhall view
@@ -0,0 +1,1 @@+{ x = { a = Type } } ∧ { x = { b = Type } }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeRecursivelyKindsB.dhall view
@@ -0,0 +1,1 @@+{ x : { a : Kind, b : Kind } }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeRecursivelyTypesA.dhall view
@@ -0,0 +1,1 @@+{ x = { a = Bool } } ∧ { x = { b = Natural } }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeRecursivelyTypesB.dhall view
@@ -0,0 +1,1 @@+{ x : { a : Type, b : Type } }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeRhsEmptyA.dhall view
@@ -0,0 +1,1 @@+{ x = True } ∧ {=}
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeRhsEmptyB.dhall view
@@ -0,0 +1,1 @@+{ x : Bool }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeTwoA.dhall view
@@ -0,0 +1,1 @@+{ x = True } ∧ { y = True }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeTwoB.dhall view
@@ -0,0 +1,1 @@+{ x : Bool, y : Bool }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeTwoKindsA.dhall view
@@ -0,0 +1,1 @@+{ x = Type } ∧ { y = Type }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeTwoKindsB.dhall view
@@ -0,0 +1,1 @@+{ x : Kind, y : Kind }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeTwoTypesA.dhall view
@@ -0,0 +1,1 @@+{ x = Bool } ∧ { y = Natural }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordMergeTwoTypesB.dhall view
@@ -0,0 +1,1 @@+{ x : Type, y : Type }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordTypeMergeDeepA.dhall view
@@ -0,0 +1,1 @@+{ a : { b : { x : Bool } } } ⩓ { a : { b : { y : Bool } } }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordTypeMergeDeepB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordTypeMergeRecursivelyA.dhall view
@@ -0,0 +1,1 @@+{ x : { a : Bool } } ⩓ { y : { b : Bool } }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordTypeMergeRecursivelyB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordTypeMergeRecursivelyKindsA.dhall view
@@ -0,0 +1,1 @@+{ x : { a : Kind } } ⩓ { y : { b : Kind } }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordTypeMergeRecursivelyKindsB.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordTypeMergeRecursivelyTypesA.dhall view
@@ -0,0 +1,1 @@+{ x : { a : Type } } ⩓ { y : { b : Type } }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordTypeMergeRecursivelyTypesB.dhall view
@@ -0,0 +1,1 @@+Kind
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordTypeMergeRhsEmptyA.dhall view
@@ -0,0 +1,1 @@+{ x : Bool } ⩓ {}
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordTypeMergeRhsEmptyB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordTypeMergeTwoA.dhall view
@@ -0,0 +1,1 @@+{ x : Bool } ⩓ { y : Bool }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordTypeMergeTwoB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordTypeMergeTwoKindsA.dhall view
@@ -0,0 +1,1 @@+{ x : Kind } ⩓ { y : Kind }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordTypeMergeTwoKindsB.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordTypeMergeTwoTypesA.dhall view
@@ -0,0 +1,1 @@+{ x : Type } ⩓ { y : Type }
+ dhall-lang/tests/type-inference/success/unit/RecursiveRecordTypeMergeTwoTypesB.dhall view
@@ -0,0 +1,1 @@+Kind
+ dhall-lang/tests/type-inference/success/unit/RightBiasedRecordMergeMixedKindsA.dhall view
@@ -0,0 +1,1 @@+{ x = {=} } ⫽ { x = Bool }
+ dhall-lang/tests/type-inference/success/unit/RightBiasedRecordMergeMixedKindsB.dhall view
@@ -0,0 +1,1 @@+{ x : Type }
+ dhall-lang/tests/type-inference/success/unit/RightBiasedRecordMergeRhsEmptyA.dhall view
@@ -0,0 +1,1 @@+{ x = {=} } ⫽ {=}
+ dhall-lang/tests/type-inference/success/unit/RightBiasedRecordMergeRhsEmptyB.dhall view
@@ -0,0 +1,1 @@+{ x : {} }
+ dhall-lang/tests/type-inference/success/unit/RightBiasedRecordMergeTwoA.dhall view
@@ -0,0 +1,1 @@+{ x = {=} } ⫽ { x = {=} }
+ dhall-lang/tests/type-inference/success/unit/RightBiasedRecordMergeTwoB.dhall view
@@ -0,0 +1,1 @@+{ x : {} }
+ dhall-lang/tests/type-inference/success/unit/RightBiasedRecordMergeTwoDifferentA.dhall view
@@ -0,0 +1,1 @@+{ x = {=} } ⫽ { x = True }
+ dhall-lang/tests/type-inference/success/unit/RightBiasedRecordMergeTwoDifferentB.dhall view
@@ -0,0 +1,1 @@+{ x : Bool }
+ dhall-lang/tests/type-inference/success/unit/RightBiasedRecordMergeTwoKindsA.dhall view
@@ -0,0 +1,1 @@+{ x = Type } ⫽ { x = Type }
+ dhall-lang/tests/type-inference/success/unit/RightBiasedRecordMergeTwoKindsB.dhall view
@@ -0,0 +1,1 @@+{ x : Kind }
+ dhall-lang/tests/type-inference/success/unit/RightBiasedRecordMergeTwoTypesA.dhall view
@@ -0,0 +1,1 @@+{ x = Bool } ⫽ { x = Natural }
+ dhall-lang/tests/type-inference/success/unit/RightBiasedRecordMergeTwoTypesB.dhall view
@@ -0,0 +1,1 @@+{ x : Type }
+ dhall-lang/tests/type-inference/success/unit/ShowConstructorEmptyA.dhall view
@@ -0,0 +1,1 @@+showConstructor <A>.A
+ dhall-lang/tests/type-inference/success/unit/ShowConstructorEmptyB.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/unit/ShowConstructorNonEmptyA.dhall view
@@ -0,0 +1,1 @@+showConstructor (< A : Bool>.A False)
+ dhall-lang/tests/type-inference/success/unit/ShowConstructorNonEmptyB.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/unit/ShowConstructorOptionalA.dhall view
@@ -0,0 +1,1 @@+showConstructor (Some 0)
+ dhall-lang/tests/type-inference/success/unit/ShowConstructorOptionalB.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/unit/SomeTrueA.dhall view
@@ -0,0 +1,1 @@+Some True
+ dhall-lang/tests/type-inference/success/unit/SomeTrueB.dhall view
@@ -0,0 +1,1 @@+Optional Bool
+ dhall-lang/tests/type-inference/success/unit/TextA.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/unit/TextB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/TextLiteralA.dhall view
@@ -0,0 +1,1 @@+"a"
+ dhall-lang/tests/type-inference/success/unit/TextLiteralB.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/unit/TextLiteralNormalizeArgumentsA.dhall view
@@ -0,0 +1,1 @@+"a${if True then "a" else "b"}"
+ dhall-lang/tests/type-inference/success/unit/TextLiteralNormalizeArgumentsB.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/unit/TextLiteralWithInterpolationA.dhall view
@@ -0,0 +1,1 @@+"a${"b"}"
+ dhall-lang/tests/type-inference/success/unit/TextLiteralWithInterpolationB.dhall view
@@ -0,0 +1,1 @@+Text
+ dhall-lang/tests/type-inference/success/unit/TextReplaceA.dhall view
@@ -0,0 +1,1 @@+Text/replace
+ dhall-lang/tests/type-inference/success/unit/TextReplaceB.dhall view
@@ -0,0 +1,1 @@+∀(needle : Text) → ∀(replacement : Text) → ∀(haystack : Text) → Text
+ dhall-lang/tests/type-inference/success/unit/TextShowA.dhall view
@@ -0,0 +1,1 @@+Text/show
+ dhall-lang/tests/type-inference/success/unit/TextShowB.dhall view
@@ -0,0 +1,1 @@+Text → Text
+ dhall-lang/tests/type-inference/success/unit/ToMapA.dhall view
@@ -0,0 +1,1 @@+toMap { foo= 1, bar= 4, baz= 9 }
+ dhall-lang/tests/type-inference/success/unit/ToMapAnnotatedA.dhall view
@@ -0,0 +1,1 @@+toMap { foo = 1, bar = 4, baz = 9 } : List { mapKey : Text, mapValue : Natural }
+ dhall-lang/tests/type-inference/success/unit/ToMapAnnotatedB.dhall view
@@ -0,0 +1,1 @@+List { mapKey : Text, mapValue : Natural }
+ dhall-lang/tests/type-inference/success/unit/ToMapB.dhall view
@@ -0,0 +1,1 @@+List { mapKey : Text, mapValue : Natural }
+ dhall-lang/tests/type-inference/success/unit/ToMapInferTypeFromRecordA.dhall view
@@ -0,0 +1,1 @@+toMap { x = λ(x : Bool) → x } : List { mapKey : Text, mapValue : ∀(x : Bool) → Bool }
+ dhall-lang/tests/type-inference/success/unit/ToMapInferTypeFromRecordB.dhall view
@@ -0,0 +1,1 @@+List { mapKey : Text, mapValue : ∀(x : Bool) → Bool }
+ dhall-lang/tests/type-inference/success/unit/TrueA.dhall view
@@ -0,0 +1,1 @@+True
+ dhall-lang/tests/type-inference/success/unit/TrueB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/TypeA.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/TypeAnnotationA.dhall view
@@ -0,0 +1,1 @@+True : Bool
+ dhall-lang/tests/type-inference/success/unit/TypeAnnotationB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/TypeAnnotationFunctionA.dhall view
@@ -0,0 +1,1 @@+(λ(x : Bool) → x) : ∀(x : Bool) → Bool
+ dhall-lang/tests/type-inference/success/unit/TypeAnnotationFunctionB.dhall view
@@ -0,0 +1,1 @@+∀(x : Bool) → Bool
+ dhall-lang/tests/type-inference/success/unit/TypeAnnotationNormalizeA.dhall view
@@ -0,0 +1,1 @@+True : { x = Bool }.x
+ dhall-lang/tests/type-inference/success/unit/TypeAnnotationNormalizeB.dhall view
@@ -0,0 +1,1 @@+Bool
+ dhall-lang/tests/type-inference/success/unit/TypeAnnotationSortA.dhall view
@@ -0,0 +1,1 @@+Kind : Sort
+ dhall-lang/tests/type-inference/success/unit/TypeAnnotationSortB.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/type-inference/success/unit/TypeB.dhall view
@@ -0,0 +1,1 @@+Kind
+ dhall-lang/tests/type-inference/success/unit/UnionConstructorEmptyFieldA.dhall view
@@ -0,0 +1,1 @@+< x | y : Bool >.x
+ dhall-lang/tests/type-inference/success/unit/UnionConstructorEmptyFieldB.dhall view
@@ -0,0 +1,1 @@+< x | y : Bool >
+ dhall-lang/tests/type-inference/success/unit/UnionConstructorFieldA.dhall view
@@ -0,0 +1,1 @@+< x : Bool >.x
+ dhall-lang/tests/type-inference/success/unit/UnionConstructorFieldB.dhall view
@@ -0,0 +1,1 @@+∀(x : Bool) → < x : Bool >
+ dhall-lang/tests/type-inference/success/unit/UnionTypeEmptyA.dhall view
@@ -0,0 +1,1 @@+<>
+ dhall-lang/tests/type-inference/success/unit/UnionTypeEmptyB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/UnionTypeKindA.dhall view
@@ -0,0 +1,1 @@+< x : Kind >
+ dhall-lang/tests/type-inference/success/unit/UnionTypeKindB.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/type-inference/success/unit/UnionTypeMixedKinds1A.dhall view
@@ -0,0 +1,1 @@+< x : Kind | y : Type >
+ dhall-lang/tests/type-inference/success/unit/UnionTypeMixedKinds1B.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/type-inference/success/unit/UnionTypeMixedKinds2A.dhall view
@@ -0,0 +1,1 @@+< x : Kind | y : Bool >
+ dhall-lang/tests/type-inference/success/unit/UnionTypeMixedKinds2B.dhall view
@@ -0,0 +1,1 @@+Sort
+ dhall-lang/tests/type-inference/success/unit/UnionTypeMixedKinds3A.dhall view
@@ -0,0 +1,1 @@+< x : Bool | y : Type >
+ dhall-lang/tests/type-inference/success/unit/UnionTypeMixedKinds3B.dhall view
@@ -0,0 +1,1 @@+Kind
+ dhall-lang/tests/type-inference/success/unit/UnionTypeMixedKinds4A.dhall view
@@ -0,0 +1,1 @@+< x : Bool | y | z : Type >
+ dhall-lang/tests/type-inference/success/unit/UnionTypeMixedKinds4B.dhall view
@@ -0,0 +1,1 @@+Kind
+ dhall-lang/tests/type-inference/success/unit/UnionTypeOneA.dhall view
@@ -0,0 +1,1 @@+< x : Bool >
+ dhall-lang/tests/type-inference/success/unit/UnionTypeOneB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/UnionTypeTypeA.dhall view
@@ -0,0 +1,1 @@+< x : Type >
+ dhall-lang/tests/type-inference/success/unit/UnionTypeTypeB.dhall view
@@ -0,0 +1,1 @@+Kind
+ dhall-lang/tests/type-inference/success/unit/WithCreateIntermediateRecordsA.dhall view
@@ -0,0 +1,3 @@+{- This test illustrates that if an intermediate record does+   not exist, the `with` operator can create one -}+{ a = 5 } with b.c = 10
+ dhall-lang/tests/type-inference/success/unit/WithCreateIntermediateRecordsB.dhall view
@@ -0,0 +1,1 @@+{ a : Natural, b : { c : Natural } }
+ dhall-lang/tests/type-inference/success/unit/WithInfersKindA.dhall view
@@ -0,0 +1,1 @@+Some ({ x = Bool } with x = 0)
+ dhall-lang/tests/type-inference/success/unit/WithInfersKindB.dhall view
@@ -0,0 +1,1 @@+Optional { x : Natural }
+ dhall-lang/tests/type-inference/success/unit/WithNestedA.dhall view
@@ -0,0 +1,4 @@+{- This test illustrates that the `with` keyword is permitted to override+   existing fields nested within a child record+-}+{ a = { p = 2, q = "hi" }, b = 5.6 } with a.p = True
+ dhall-lang/tests/type-inference/success/unit/WithNestedB.dhall view
@@ -0,0 +1,1 @@+{ a : { p : Bool, q : Text }, b : Double }
+ dhall-lang/tests/type-inference/success/unit/WithNewFieldA.dhall view
@@ -0,0 +1,4 @@+{- This test illustrates how the `with` keyword is permitted to extend a record+   with new fields+-}+{ a = 1 } with b = 2
+ dhall-lang/tests/type-inference/success/unit/WithNewFieldB.dhall view
@@ -0,0 +1,1 @@+{ a : Natural, b : Natural }
+ dhall-lang/tests/type-inference/success/unit/WithNewTypeA.dhall view
@@ -0,0 +1,4 @@+{- This test illustrates that the `with` keyword is permitted to override+   existing fields with a value of a new type (just like the `//` operator)+-}+{ a = 1 } with a = True
+ dhall-lang/tests/type-inference/success/unit/WithNewTypeB.dhall view
@@ -0,0 +1,1 @@+{ a : Bool }
+ dhall-lang/tests/type-inference/success/unit/WithOptionalTypeUnchangedA.dhall view
@@ -0,0 +1,1 @@+(Some 0) with ? = 1
+ dhall-lang/tests/type-inference/success/unit/WithOptionalTypeUnchangedB.dhall view
@@ -0,0 +1,1 @@+Optional Natural
+ dhall-lang/tests/type-inference/success/unit/time/DateA.dhall view
@@ -0,0 +1,1 @@+Date
+ dhall-lang/tests/type-inference/success/unit/time/DateB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/time/DateLiteralA.dhall view
@@ -0,0 +1,1 @@+2000-01-01
+ dhall-lang/tests/type-inference/success/unit/time/DateLiteralB.dhall view
@@ -0,0 +1,1 @@+Date
+ dhall-lang/tests/type-inference/success/unit/time/DateTimeLiteralA.dhall view
@@ -0,0 +1,1 @@+2000-01-01T12:00:00
+ dhall-lang/tests/type-inference/success/unit/time/DateTimeLiteralB.dhall view
@@ -0,0 +1,1 @@+{ date : Date, time : Time }
+ dhall-lang/tests/type-inference/success/unit/time/DateTimeTimeZoneLiteralA.dhall view
@@ -0,0 +1,1 @@+2000-01-01T12:00:00+08:00
+ dhall-lang/tests/type-inference/success/unit/time/DateTimeTimeZoneLiteralB.dhall view
@@ -0,0 +1,1 @@+{ date : Date, time : Time, timeZone : TimeZone }
+ dhall-lang/tests/type-inference/success/unit/time/TimeA.dhall view
@@ -0,0 +1,1 @@+Time
+ dhall-lang/tests/type-inference/success/unit/time/TimeB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/time/TimeLiteralA.dhall view
@@ -0,0 +1,1 @@+12:00:00
+ dhall-lang/tests/type-inference/success/unit/time/TimeLiteralB.dhall view
@@ -0,0 +1,1 @@+Time
+ dhall-lang/tests/type-inference/success/unit/time/TimeTimeZoneLiteralA.dhall view
@@ -0,0 +1,1 @@+12:00:00+08:00
+ dhall-lang/tests/type-inference/success/unit/time/TimeTimeZoneLiteralB.dhall view
@@ -0,0 +1,1 @@+{ time : Time, timeZone : TimeZone }
+ dhall-lang/tests/type-inference/success/unit/time/TimeZoneA.dhall view
@@ -0,0 +1,1 @@+TimeZone
+ dhall-lang/tests/type-inference/success/unit/time/TimeZoneB.dhall view
@@ -0,0 +1,1 @@+Type
+ dhall-lang/tests/type-inference/success/unit/time/TimeZoneLiteralA.dhall view
@@ -0,0 +1,1 @@++08:00
+ dhall-lang/tests/type-inference/success/unit/time/TimeZoneLiteralB.dhall view
@@ -0,0 +1,1 @@+TimeZone
− dhall-lang/tests/typecheck/data/importBoundary.dhall
@@ -1,3 +0,0 @@--- This file contains a free variable. This should be a type error, even if the variable--- is in scope in the importing expression-x
− dhall-lang/tests/typecheck/failure/combineMixedRecords.dhall
@@ -1,1 +0,0 @@-{ foo = 1 } ∧ { bar = Text }
− dhall-lang/tests/typecheck/failure/customHeadersUsingBoundVariable.dhall
@@ -1,15 +0,0 @@-{- This is a type error because the custom headers are type-checked with an-   empty context.  This is necessary because:--   * import resolution precedes β-normalization-   * we also don't want custom headers to leak program state anyway--   This should fail due to the `x` within the custom header being an unbound-   variable--}--let x = "Bar"--in https://httpbin.org/headers-     using [ { header = "Foo", value = x } ]-     as Text
− dhall-lang/tests/typecheck/failure/duplicateFields.dhall
@@ -1,1 +0,0 @@-{ a = 1, a = 2 }
− dhall-lang/tests/typecheck/failure/hurkensParadox.dhall
@@ -1,49 +0,0 @@-    let bottom : Type = ∀(any : Type) → any--in  let not : Type → Type = λ(p : Type) → p → bottom--in  let pow = λ(X : Kind) → X → Type--in  let U = ∀(X : Kind) → (pow (pow X) → X) → pow (pow X)--in  let tau-        : pow (pow U) → U-        =   λ(t : pow (pow U))-          → λ(X : Kind)-          → λ(f : pow (pow X) → X)-          → λ(p : pow X)-          → t (λ(x : U) → p (f (x X f)))--in  let sigma : U → pow (pow U) = λ(s : U) → s U (λ(t : pow (pow U)) → tau t)--in  let Delta-        : pow U-        = λ(y : U) → not (∀(p : pow U) → sigma y p → p (tau (sigma y)))--in  let Omega : U = tau (λ(p : pow U) → ∀(x : U) → sigma x p → p x)--in  let Theta : Type = ∀(p : pow U) → (∀(x : U) → sigma x p → p x) → p Omega--in  let D : Type = ∀(p : pow U) → sigma Omega p → p (tau (sigma Omega))--in  let lem1-        : ∀(p : pow U) → (∀(x : U) → sigma x p → p x) → p Omega-        =   λ(p : pow U)-          → λ(t1 : ∀(x : U) → sigma x p → p x)-          → t1 Omega (λ(x : U) → t1 (tau (sigma x)))--in  let lem3 : D = λ(p : pow U) → lem1 (λ(y : U) → p (tau (sigma y)))--in  let lem2-        : not D-        = lem1-          Delta-          (   λ(x : U)-            → λ(H2 : sigma x Delta)-            → λ(H3 : ∀(p : pow U) → sigma x p → p (tau (sigma x)))-            → H3 Delta H2 (λ(pp : pow U) → H3 (λ(y : U) → pp (tau (sigma y))))-          )--in  let evidence : bottom = lem2 lem3--in  evidence
− dhall-lang/tests/typecheck/failure/importBoundary.dhall
@@ -1,1 +0,0 @@-\(x: Bool) -> ../data/importBoundary.dhall
− dhall-lang/tests/typecheck/failure/mixedUnions.dhall
@@ -1,1 +0,0 @@-< Left : Natural | Right : Type >
− dhall-lang/tests/typecheck/failure/preferMixedRecords.dhall
@@ -1,1 +0,0 @@-{ foo = 1 } ⫽ { bar = Text }
− dhall-lang/tests/typecheck/success/accessEncodedTypeA.dhall
@@ -1,4 +0,0 @@-  λ ( record-    : ∀(k : Kind) → ∀(makeRecord : ∀(x : Type) → ∀(y : Type → Type) → k) → k-    )-→ record Type (λ(x : Type) → λ(y : Type → Type) → x)
− dhall-lang/tests/typecheck/success/accessEncodedTypeB.dhall
@@ -1,4 +0,0 @@-  ∀ ( record-    : ∀(k : Kind) → ∀(makeRecord : ∀(x : Type) → ∀(y : Type → Type) → k) → k-    )-→ Type
− dhall-lang/tests/typecheck/success/accessTypeA.dhall
@@ -1,1 +0,0 @@-λ(record : { x : Type, y : Type → Type }) → record.x
− dhall-lang/tests/typecheck/success/accessTypeB.dhall
@@ -1,1 +0,0 @@-∀(record : { x : Type, y : Type → Type }) → Type
− dhall-lang/tests/typecheck/success/prelude/Bool/and/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Bool/and [ True, False, True ]
− dhall-lang/tests/typecheck/success/prelude/Bool/and/0B.dhall
@@ -1,1 +0,0 @@-Bool
− dhall-lang/tests/typecheck/success/prelude/Bool/and/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Bool/and ([] : List Bool)
− dhall-lang/tests/typecheck/success/prelude/Bool/and/1B.dhall
@@ -1,1 +0,0 @@-Bool
− dhall-lang/tests/typecheck/success/prelude/Bool/build/0A.dhall
@@ -1,2 +0,0 @@-../../../../../../Prelude/Bool/build -(λ(bool : Type) → λ(true : bool) → λ(false : bool) → true)
− dhall-lang/tests/typecheck/success/prelude/Bool/build/0B.dhall
@@ -1,1 +0,0 @@-Bool
− dhall-lang/tests/typecheck/success/prelude/Bool/build/1A.dhall
@@ -1,2 +0,0 @@-../../../../../../Prelude/Bool/build -(λ(bool : Type) → λ(true : bool) → λ(false : bool) → false)
− dhall-lang/tests/typecheck/success/prelude/Bool/build/1B.dhall
@@ -1,1 +0,0 @@-Bool
− dhall-lang/tests/typecheck/success/prelude/Bool/even/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Bool/even [ False, True, False ]
− dhall-lang/tests/typecheck/success/prelude/Bool/even/0B.dhall
@@ -1,1 +0,0 @@-Bool
− dhall-lang/tests/typecheck/success/prelude/Bool/even/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Bool/even [ False, True ]
− dhall-lang/tests/typecheck/success/prelude/Bool/even/1B.dhall
@@ -1,1 +0,0 @@-Bool
− dhall-lang/tests/typecheck/success/prelude/Bool/even/2A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Bool/even [ False ]
− dhall-lang/tests/typecheck/success/prelude/Bool/even/2B.dhall
@@ -1,1 +0,0 @@-Bool
− dhall-lang/tests/typecheck/success/prelude/Bool/even/3A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Bool/even ([] : List Bool)
− dhall-lang/tests/typecheck/success/prelude/Bool/even/3B.dhall
@@ -1,1 +0,0 @@-Bool
− dhall-lang/tests/typecheck/success/prelude/Bool/fold/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Bool/fold True Natural 0 1
− dhall-lang/tests/typecheck/success/prelude/Bool/fold/0B.dhall
@@ -1,1 +0,0 @@-Natural
− dhall-lang/tests/typecheck/success/prelude/Bool/fold/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Bool/fold False Natural 0 1
− dhall-lang/tests/typecheck/success/prelude/Bool/fold/1B.dhall
@@ -1,1 +0,0 @@-Natural
− dhall-lang/tests/typecheck/success/prelude/Bool/not/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Bool/not True
− dhall-lang/tests/typecheck/success/prelude/Bool/not/0B.dhall
@@ -1,1 +0,0 @@-Bool
− dhall-lang/tests/typecheck/success/prelude/Bool/not/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Bool/not False
− dhall-lang/tests/typecheck/success/prelude/Bool/not/1B.dhall
@@ -1,1 +0,0 @@-Bool
− dhall-lang/tests/typecheck/success/prelude/Bool/odd/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Bool/odd [ True, False, True ]
− dhall-lang/tests/typecheck/success/prelude/Bool/odd/0B.dhall
@@ -1,1 +0,0 @@-Bool
− dhall-lang/tests/typecheck/success/prelude/Bool/odd/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Bool/odd [ True, False ]
− dhall-lang/tests/typecheck/success/prelude/Bool/odd/1B.dhall
@@ -1,1 +0,0 @@-Bool
− dhall-lang/tests/typecheck/success/prelude/Bool/odd/2A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Bool/odd [ True ]
− dhall-lang/tests/typecheck/success/prelude/Bool/odd/2B.dhall
@@ -1,1 +0,0 @@-Bool
− dhall-lang/tests/typecheck/success/prelude/Bool/odd/3A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Bool/odd ([] : List Bool)
− dhall-lang/tests/typecheck/success/prelude/Bool/odd/3B.dhall
@@ -1,1 +0,0 @@-Bool
− dhall-lang/tests/typecheck/success/prelude/Bool/or/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Bool/or [ True, False, True ]
− dhall-lang/tests/typecheck/success/prelude/Bool/or/0B.dhall
@@ -1,1 +0,0 @@-Bool
− dhall-lang/tests/typecheck/success/prelude/Bool/or/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Bool/or ([] : List Bool)
− dhall-lang/tests/typecheck/success/prelude/Bool/or/1B.dhall
@@ -1,1 +0,0 @@-Bool
− dhall-lang/tests/typecheck/success/prelude/Bool/show/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Bool/show True
− dhall-lang/tests/typecheck/success/prelude/Bool/show/0B.dhall
@@ -1,1 +0,0 @@-Text
− dhall-lang/tests/typecheck/success/prelude/Bool/show/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Bool/show False
− dhall-lang/tests/typecheck/success/prelude/Bool/show/1B.dhall
@@ -1,1 +0,0 @@-Text
− dhall-lang/tests/typecheck/success/prelude/Double/show/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Double/show -3.1
− dhall-lang/tests/typecheck/success/prelude/Double/show/0B.dhall
@@ -1,1 +0,0 @@-Text
− dhall-lang/tests/typecheck/success/prelude/Double/show/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Double/show 0.4
− dhall-lang/tests/typecheck/success/prelude/Double/show/1B.dhall
@@ -1,1 +0,0 @@-Text
− dhall-lang/tests/typecheck/success/prelude/Integer/show/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Integer/show -3
− dhall-lang/tests/typecheck/success/prelude/Integer/show/0B.dhall
@@ -1,1 +0,0 @@-Text
− dhall-lang/tests/typecheck/success/prelude/Integer/show/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Integer/show +0
− dhall-lang/tests/typecheck/success/prelude/Integer/show/1B.dhall
@@ -1,1 +0,0 @@-Text
− dhall-lang/tests/typecheck/success/prelude/Integer/toDouble/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Integer/toDouble -3
− dhall-lang/tests/typecheck/success/prelude/Integer/toDouble/0B.dhall
@@ -1,1 +0,0 @@-Double
− dhall-lang/tests/typecheck/success/prelude/Integer/toDouble/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Integer/toDouble +2
− dhall-lang/tests/typecheck/success/prelude/Integer/toDouble/1B.dhall
@@ -1,1 +0,0 @@-Double
− dhall-lang/tests/typecheck/success/prelude/List/all/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/all Natural Natural/even [ 2, 3, 5 ]
− dhall-lang/tests/typecheck/success/prelude/List/all/0B.dhall
@@ -1,1 +0,0 @@-Bool
− dhall-lang/tests/typecheck/success/prelude/List/all/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/all Natural Natural/even ([] : List Natural)
− dhall-lang/tests/typecheck/success/prelude/List/all/1B.dhall
@@ -1,1 +0,0 @@-Bool
− dhall-lang/tests/typecheck/success/prelude/List/any/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/any Natural Natural/even [ 2, 3, 5 ]
− dhall-lang/tests/typecheck/success/prelude/List/any/0B.dhall
@@ -1,1 +0,0 @@-Bool
− dhall-lang/tests/typecheck/success/prelude/List/any/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/any Natural Natural/even ([] : List Natural)
− dhall-lang/tests/typecheck/success/prelude/List/any/1B.dhall
@@ -1,1 +0,0 @@-Bool
− dhall-lang/tests/typecheck/success/prelude/List/build/0A.dhall
@@ -1,7 +0,0 @@-../../../../../../Prelude/List/build-Text-( λ(list : Type)-→ λ(cons : Text → list → list)-→ λ(nil : list)-→ cons "ABC" (cons "DEF" nil)-)
− dhall-lang/tests/typecheck/success/prelude/List/build/0B.dhall
@@ -1,1 +0,0 @@-List Text
− dhall-lang/tests/typecheck/success/prelude/List/build/1A.dhall
@@ -1,7 +0,0 @@-../../../../../../Prelude/List/build-Text-( λ(list : Type)-→ λ(cons : Text → list → list)-→ λ(nil : list)-→ nil-)
− dhall-lang/tests/typecheck/success/prelude/List/build/1B.dhall
@@ -1,1 +0,0 @@-List Text
− dhall-lang/tests/typecheck/success/prelude/List/concat/0A.dhall
@@ -1,5 +0,0 @@-../../../../../../Prelude/List/concat Natural-[ [ 0, 1, 2 ]-, [ 3, 4 ]-, [ 5, 6, 7, 8 ]-]
− dhall-lang/tests/typecheck/success/prelude/List/concat/0B.dhall
@@ -1,1 +0,0 @@-List Natural
− dhall-lang/tests/typecheck/success/prelude/List/concat/1A.dhall
@@ -1,5 +0,0 @@-../../../../../../Prelude/List/concat Natural-[ [] : List Natural-, [] : List Natural-, [] : List Natural-]
− dhall-lang/tests/typecheck/success/prelude/List/concat/1B.dhall
@@ -1,1 +0,0 @@-List Natural
− dhall-lang/tests/typecheck/success/prelude/List/concatMap/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/concatMap Natural Natural (λ(n : Natural) → [ n, n ]) [ 2, 3, 5 ]
− dhall-lang/tests/typecheck/success/prelude/List/concatMap/0B.dhall
@@ -1,1 +0,0 @@-List Natural
− dhall-lang/tests/typecheck/success/prelude/List/concatMap/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/concatMap Natural Natural (λ(n : Natural) → [ n, n ]) ([] : List Natural)
− dhall-lang/tests/typecheck/success/prelude/List/concatMap/1B.dhall
@@ -1,1 +0,0 @@-List Natural
− dhall-lang/tests/typecheck/success/prelude/List/filter/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/filter Natural Natural/even [ 2, 3, 5 ]
− dhall-lang/tests/typecheck/success/prelude/List/filter/0B.dhall
@@ -1,1 +0,0 @@-List Natural
− dhall-lang/tests/typecheck/success/prelude/List/filter/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/filter Natural Natural/odd [ 2, 3, 5 ]
− dhall-lang/tests/typecheck/success/prelude/List/filter/1B.dhall
@@ -1,1 +0,0 @@-List Natural
− dhall-lang/tests/typecheck/success/prelude/List/fold/0A.dhall
@@ -1,6 +0,0 @@-../../../../../../Prelude/List/fold-Natural-[ 2, 3, 5 ]-Natural-(λ(x : Natural) → λ(y : Natural) → x + y)-0
− dhall-lang/tests/typecheck/success/prelude/List/fold/0B.dhall
@@ -1,1 +0,0 @@-Natural
− dhall-lang/tests/typecheck/success/prelude/List/fold/1A.dhall
@@ -1,7 +0,0 @@-  λ(nil : Natural)-→ ../../../../../../Prelude/List/fold-  Natural-  [ 2, 3, 5 ]-  Natural-  (λ(x : Natural) → λ(y : Natural) → x + y)-  nil
− dhall-lang/tests/typecheck/success/prelude/List/fold/1B.dhall
@@ -1,1 +0,0 @@-∀(nil : Natural) → Natural
− dhall-lang/tests/typecheck/success/prelude/List/fold/2A.dhall
@@ -1,4 +0,0 @@-  λ(list : Type)-→ λ(cons : Natural → list → list)-→ λ(nil : list)-→ ../../../../../../Prelude/List/fold Natural [ 2, 3, 5 ] list cons nil
− dhall-lang/tests/typecheck/success/prelude/List/fold/2B.dhall
@@ -1,1 +0,0 @@-∀(list : Type) → ∀(cons : Natural → list → list) → ∀(nil : list) → list
− dhall-lang/tests/typecheck/success/prelude/List/generate/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/generate 5 Bool Natural/even
− dhall-lang/tests/typecheck/success/prelude/List/generate/0B.dhall
@@ -1,1 +0,0 @@-List Bool
− dhall-lang/tests/typecheck/success/prelude/List/generate/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/generate 0 Bool Natural/even
− dhall-lang/tests/typecheck/success/prelude/List/generate/1B.dhall
@@ -1,1 +0,0 @@-List Bool
− dhall-lang/tests/typecheck/success/prelude/List/head/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/head Natural [ 0, 1, 2 ]
− dhall-lang/tests/typecheck/success/prelude/List/head/0B.dhall
@@ -1,1 +0,0 @@-Optional Natural
− dhall-lang/tests/typecheck/success/prelude/List/head/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/head Natural ([] : List Natural)
− dhall-lang/tests/typecheck/success/prelude/List/head/1B.dhall
@@ -1,1 +0,0 @@-Optional Natural
− dhall-lang/tests/typecheck/success/prelude/List/indexed/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/indexed Bool [ True, False, True ]
− dhall-lang/tests/typecheck/success/prelude/List/indexed/0B.dhall
@@ -1,1 +0,0 @@-List { index : Natural, value : Bool }
− dhall-lang/tests/typecheck/success/prelude/List/indexed/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/indexed Bool ([] : List Bool)
− dhall-lang/tests/typecheck/success/prelude/List/indexed/1B.dhall
@@ -1,1 +0,0 @@-List { index : Natural, value : Bool }
− dhall-lang/tests/typecheck/success/prelude/List/iterate/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/iterate 10 Natural (λ(x : Natural) → x * 2) 1
− dhall-lang/tests/typecheck/success/prelude/List/iterate/0B.dhall
@@ -1,1 +0,0 @@-List Natural
− dhall-lang/tests/typecheck/success/prelude/List/iterate/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/iterate 0 Natural (λ(x : Natural) → x * 2) 1
− dhall-lang/tests/typecheck/success/prelude/List/iterate/1B.dhall
@@ -1,1 +0,0 @@-List Natural
− dhall-lang/tests/typecheck/success/prelude/List/last/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/last Natural [ 0, 1, 2 ]
− dhall-lang/tests/typecheck/success/prelude/List/last/0B.dhall
@@ -1,1 +0,0 @@-Optional Natural
− dhall-lang/tests/typecheck/success/prelude/List/last/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/last Natural ([] : List Natural)
− dhall-lang/tests/typecheck/success/prelude/List/last/1B.dhall
@@ -1,1 +0,0 @@-Optional Natural
− dhall-lang/tests/typecheck/success/prelude/List/length/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/length Natural [ 0, 1, 2 ]
− dhall-lang/tests/typecheck/success/prelude/List/length/0B.dhall
@@ -1,1 +0,0 @@-Natural
− dhall-lang/tests/typecheck/success/prelude/List/length/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/length Natural ([] : List Natural)
− dhall-lang/tests/typecheck/success/prelude/List/length/1B.dhall
@@ -1,1 +0,0 @@-Natural
− dhall-lang/tests/typecheck/success/prelude/List/map/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/map Natural Bool Natural/even [ 2, 3, 5 ]
− dhall-lang/tests/typecheck/success/prelude/List/map/0B.dhall
@@ -1,1 +0,0 @@-List Bool
− dhall-lang/tests/typecheck/success/prelude/List/map/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/map Natural Bool Natural/even ([] : List Natural)
− dhall-lang/tests/typecheck/success/prelude/List/map/1B.dhall
@@ -1,1 +0,0 @@-List Bool
− dhall-lang/tests/typecheck/success/prelude/List/null/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/null Natural [ 0, 1, 2 ]
− dhall-lang/tests/typecheck/success/prelude/List/null/0B.dhall
@@ -1,1 +0,0 @@-Bool
− dhall-lang/tests/typecheck/success/prelude/List/null/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/null Natural ([] : List Natural)
− dhall-lang/tests/typecheck/success/prelude/List/null/1B.dhall
@@ -1,1 +0,0 @@-Bool
− dhall-lang/tests/typecheck/success/prelude/List/replicate/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/replicate 9 Natural 1
− dhall-lang/tests/typecheck/success/prelude/List/replicate/0B.dhall
@@ -1,1 +0,0 @@-List Natural
− dhall-lang/tests/typecheck/success/prelude/List/replicate/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/replicate 0 Natural 1
− dhall-lang/tests/typecheck/success/prelude/List/replicate/1B.dhall
@@ -1,1 +0,0 @@-List Natural
− dhall-lang/tests/typecheck/success/prelude/List/reverse/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/reverse Natural [ 0, 1, 2 ]
− dhall-lang/tests/typecheck/success/prelude/List/reverse/0B.dhall
@@ -1,1 +0,0 @@-List Natural
− dhall-lang/tests/typecheck/success/prelude/List/reverse/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/reverse Natural ([] : List Natural)
− dhall-lang/tests/typecheck/success/prelude/List/reverse/1B.dhall
@@ -1,1 +0,0 @@-List Natural
− dhall-lang/tests/typecheck/success/prelude/List/shifted/0A.dhall
@@ -1,15 +0,0 @@-../../../../../../Prelude/List/shifted-Bool-[ [ { index = 0, value = True }-  , { index = 1, value = True }-  , { index = 2, value = False }-  ]-, [ { index = 0, value = False }-  , { index = 1, value = False }-  ]-, [ { index = 0, value = True }-  , { index = 1, value = True }-  , { index = 2, value = True }-  , { index = 3, value = True }-  ]-]
− dhall-lang/tests/typecheck/success/prelude/List/shifted/0B.dhall
@@ -1,1 +0,0 @@-List { index : Natural, value : Bool }
− dhall-lang/tests/typecheck/success/prelude/List/shifted/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/shifted Bool ([] : List (List { index : Natural, value : Bool }))
− dhall-lang/tests/typecheck/success/prelude/List/shifted/1B.dhall
@@ -1,1 +0,0 @@-List { index : Natural, value : Bool }
− dhall-lang/tests/typecheck/success/prelude/List/unzip/0A.dhall
@@ -1,7 +0,0 @@-../../../../../../Prelude/List/unzip-Text-Bool-[ { _1 = "ABC", _2 = True }-, { _1 = "DEF", _2 = False }-, { _1 = "GHI", _2 = True }-]
− dhall-lang/tests/typecheck/success/prelude/List/unzip/0B.dhall
@@ -1,1 +0,0 @@-{ _1 : List Text, _2 : List Bool }
− dhall-lang/tests/typecheck/success/prelude/List/unzip/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/List/unzip Text Bool ([] : List { _1 : Text, _2 : Bool })
− dhall-lang/tests/typecheck/success/prelude/List/unzip/1B.dhall
@@ -1,1 +0,0 @@-{ _1 : List Text, _2 : List Bool }
− dhall-lang/tests/typecheck/success/prelude/Monoid/00A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Bool/and
− dhall-lang/tests/typecheck/success/prelude/Monoid/00B.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Monoid Bool
− dhall-lang/tests/typecheck/success/prelude/Monoid/01A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Bool/or
− dhall-lang/tests/typecheck/success/prelude/Monoid/01B.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Monoid Bool
− dhall-lang/tests/typecheck/success/prelude/Monoid/02A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Bool/even
− dhall-lang/tests/typecheck/success/prelude/Monoid/02B.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Monoid Bool
− dhall-lang/tests/typecheck/success/prelude/Monoid/03A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Bool/odd
− dhall-lang/tests/typecheck/success/prelude/Monoid/03B.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Monoid Bool
− dhall-lang/tests/typecheck/success/prelude/Monoid/04A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/List/concat
− dhall-lang/tests/typecheck/success/prelude/Monoid/04B.dhall
@@ -1,1 +0,0 @@-∀(a : Type) → ../../../../../Prelude/Monoid (List a)
− dhall-lang/tests/typecheck/success/prelude/Monoid/05A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/List/shifted
− dhall-lang/tests/typecheck/success/prelude/Monoid/05B.dhall
@@ -1,1 +0,0 @@-∀(a : Type) → ../../../../../Prelude/Monoid (List { index : Natural, value : a })
− dhall-lang/tests/typecheck/success/prelude/Monoid/06A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Natural/sum
− dhall-lang/tests/typecheck/success/prelude/Monoid/06B.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Monoid Natural
− dhall-lang/tests/typecheck/success/prelude/Monoid/07A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Natural/product
− dhall-lang/tests/typecheck/success/prelude/Monoid/07B.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Monoid Natural
− dhall-lang/tests/typecheck/success/prelude/Monoid/08A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Optional/head
− dhall-lang/tests/typecheck/success/prelude/Monoid/08B.dhall
@@ -1,1 +0,0 @@-∀(a : Type) → ../../../../../Prelude/Monoid (Optional a)
− dhall-lang/tests/typecheck/success/prelude/Monoid/09A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Optional/last
− dhall-lang/tests/typecheck/success/prelude/Monoid/09B.dhall
@@ -1,1 +0,0 @@-∀(a : Type) → ../../../../../Prelude/Monoid (Optional a)
− dhall-lang/tests/typecheck/success/prelude/Monoid/10A.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Text/concat
− dhall-lang/tests/typecheck/success/prelude/Monoid/10B.dhall
@@ -1,1 +0,0 @@-../../../../../Prelude/Monoid Text
− dhall-lang/tests/typecheck/success/prelude/Natural/build/0A.dhall
@@ -1,6 +0,0 @@-../../../../../../Prelude/Natural/build-( λ(natural : Type)-→ λ(succ : natural → natural)-→ λ(zero : natural)-→ succ (succ (succ zero))-)
− dhall-lang/tests/typecheck/success/prelude/Natural/build/0B.dhall
@@ -1,1 +0,0 @@-Natural
− dhall-lang/tests/typecheck/success/prelude/Natural/build/1A.dhall
@@ -1,6 +0,0 @@-../../../../../../Prelude/Natural/build-( λ(natural : Type)-→ λ(succ : natural → natural)-→ λ(zero : natural)-→ zero-)
− dhall-lang/tests/typecheck/success/prelude/Natural/build/1B.dhall
@@ -1,1 +0,0 @@-Natural
− dhall-lang/tests/typecheck/success/prelude/Natural/enumerate/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/enumerate 10
− dhall-lang/tests/typecheck/success/prelude/Natural/enumerate/0B.dhall
@@ -1,1 +0,0 @@-List Natural
− dhall-lang/tests/typecheck/success/prelude/Natural/enumerate/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/enumerate 0
− dhall-lang/tests/typecheck/success/prelude/Natural/enumerate/1B.dhall
@@ -1,1 +0,0 @@-List Natural
− dhall-lang/tests/typecheck/success/prelude/Natural/even/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/even 3
− dhall-lang/tests/typecheck/success/prelude/Natural/even/0B.dhall
@@ -1,1 +0,0 @@-Bool
− dhall-lang/tests/typecheck/success/prelude/Natural/even/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/even 0
− dhall-lang/tests/typecheck/success/prelude/Natural/even/1B.dhall
@@ -1,1 +0,0 @@-Bool
− dhall-lang/tests/typecheck/success/prelude/Natural/fold/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/fold 3 Natural (λ(x : Natural) → 5 * x) 1
− dhall-lang/tests/typecheck/success/prelude/Natural/fold/0B.dhall
@@ -1,1 +0,0 @@-Natural
− dhall-lang/tests/typecheck/success/prelude/Natural/fold/1A.dhall
@@ -1,1 +0,0 @@-λ(zero : Natural) → ../../../../../../Prelude/Natural/fold 3 Natural (λ(x : Natural) → 5 * x) zero
− dhall-lang/tests/typecheck/success/prelude/Natural/fold/1B.dhall
@@ -1,1 +0,0 @@-∀(zero : Natural) → Natural
− dhall-lang/tests/typecheck/success/prelude/Natural/fold/2A.dhall
@@ -1,4 +0,0 @@-  λ(natural : Type)-→ λ(succ : natural → natural)-→ λ(zero : natural)-→ ../../../../../../Prelude/Natural/fold 3 natural succ zero
− dhall-lang/tests/typecheck/success/prelude/Natural/fold/2B.dhall
@@ -1,1 +0,0 @@-∀(natural : Type) → ∀(succ : natural → natural) → ∀(zero : natural) → natural
− dhall-lang/tests/typecheck/success/prelude/Natural/isZero/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/isZero 2
− dhall-lang/tests/typecheck/success/prelude/Natural/isZero/0B.dhall
@@ -1,1 +0,0 @@-Bool
− dhall-lang/tests/typecheck/success/prelude/Natural/isZero/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/isZero 0
− dhall-lang/tests/typecheck/success/prelude/Natural/isZero/1B.dhall
@@ -1,1 +0,0 @@-Bool
− dhall-lang/tests/typecheck/success/prelude/Natural/odd/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/odd 3
− dhall-lang/tests/typecheck/success/prelude/Natural/odd/0B.dhall
@@ -1,1 +0,0 @@-Bool
− dhall-lang/tests/typecheck/success/prelude/Natural/odd/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/odd 0
− dhall-lang/tests/typecheck/success/prelude/Natural/odd/1B.dhall
@@ -1,1 +0,0 @@-Bool
− dhall-lang/tests/typecheck/success/prelude/Natural/product/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/product [ 2, 3, 5 ]
− dhall-lang/tests/typecheck/success/prelude/Natural/product/0B.dhall
@@ -1,1 +0,0 @@-Natural
− dhall-lang/tests/typecheck/success/prelude/Natural/product/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/product ([] : List Natural)
− dhall-lang/tests/typecheck/success/prelude/Natural/product/1B.dhall
@@ -1,1 +0,0 @@-Natural
− dhall-lang/tests/typecheck/success/prelude/Natural/show/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/show 3
− dhall-lang/tests/typecheck/success/prelude/Natural/show/0B.dhall
@@ -1,1 +0,0 @@-Text
− dhall-lang/tests/typecheck/success/prelude/Natural/show/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/show 0
− dhall-lang/tests/typecheck/success/prelude/Natural/show/1B.dhall
@@ -1,1 +0,0 @@-Text
− dhall-lang/tests/typecheck/success/prelude/Natural/sum/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/sum [ 2, 3, 5 ]
− dhall-lang/tests/typecheck/success/prelude/Natural/sum/0B.dhall
@@ -1,1 +0,0 @@-Natural
− dhall-lang/tests/typecheck/success/prelude/Natural/sum/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/sum ([] : List Natural)
− dhall-lang/tests/typecheck/success/prelude/Natural/sum/1B.dhall
@@ -1,1 +0,0 @@-Natural
− dhall-lang/tests/typecheck/success/prelude/Natural/toDouble/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/toDouble 3
− dhall-lang/tests/typecheck/success/prelude/Natural/toDouble/0B.dhall
@@ -1,1 +0,0 @@-Double
− dhall-lang/tests/typecheck/success/prelude/Natural/toDouble/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/toDouble 0
− dhall-lang/tests/typecheck/success/prelude/Natural/toDouble/1B.dhall
@@ -1,1 +0,0 @@-Double
− dhall-lang/tests/typecheck/success/prelude/Natural/toInteger/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/toInteger 3
− dhall-lang/tests/typecheck/success/prelude/Natural/toInteger/0B.dhall
@@ -1,1 +0,0 @@-Integer
− dhall-lang/tests/typecheck/success/prelude/Natural/toInteger/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Natural/toInteger 0
− dhall-lang/tests/typecheck/success/prelude/Natural/toInteger/1B.dhall
@@ -1,1 +0,0 @@-Integer
− dhall-lang/tests/typecheck/success/prelude/Optional/all/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/all Natural Natural/even (Some 3)
− dhall-lang/tests/typecheck/success/prelude/Optional/all/0B.dhall
@@ -1,1 +0,0 @@-Bool
− dhall-lang/tests/typecheck/success/prelude/Optional/all/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/all Natural Natural/even (None Natural)
− dhall-lang/tests/typecheck/success/prelude/Optional/all/1B.dhall
@@ -1,1 +0,0 @@-Bool
− dhall-lang/tests/typecheck/success/prelude/Optional/any/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/any Natural Natural/even (Some 2)
− dhall-lang/tests/typecheck/success/prelude/Optional/any/0B.dhall
@@ -1,1 +0,0 @@-Bool
− dhall-lang/tests/typecheck/success/prelude/Optional/any/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/any Natural Natural/even (None Natural)
− dhall-lang/tests/typecheck/success/prelude/Optional/any/1B.dhall
@@ -1,1 +0,0 @@-Bool
− dhall-lang/tests/typecheck/success/prelude/Optional/build/0A.dhall
@@ -1,7 +0,0 @@-../../../../../../Prelude/Optional/build-Natural-( λ(optional : Type)-→ λ(some : Natural → optional)-→ λ(none : optional)-→ some 1-)
− dhall-lang/tests/typecheck/success/prelude/Optional/build/0B.dhall
@@ -1,1 +0,0 @@-Optional Natural
− dhall-lang/tests/typecheck/success/prelude/Optional/build/1A.dhall
@@ -1,7 +0,0 @@-../../../../../../Prelude/Optional/build-Natural-( λ(optional : Type)-→ λ(some : Natural → optional)-→ λ(none : optional)-→ none-)
− dhall-lang/tests/typecheck/success/prelude/Optional/build/1B.dhall
@@ -1,1 +0,0 @@-Optional Natural
− dhall-lang/tests/typecheck/success/prelude/Optional/concat/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/concat Natural (Some (Some 1))
− dhall-lang/tests/typecheck/success/prelude/Optional/concat/0B.dhall
@@ -1,1 +0,0 @@-Optional Natural
− dhall-lang/tests/typecheck/success/prelude/Optional/concat/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/concat Natural (Some (None Natural))
− dhall-lang/tests/typecheck/success/prelude/Optional/concat/1B.dhall
@@ -1,1 +0,0 @@-Optional Natural
− dhall-lang/tests/typecheck/success/prelude/Optional/concat/2A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/concat Natural (None (Optional Natural))
− dhall-lang/tests/typecheck/success/prelude/Optional/concat/2B.dhall
@@ -1,1 +0,0 @@-Optional Natural
− dhall-lang/tests/typecheck/success/prelude/Optional/filter/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/filter Natural Natural/even (Some 2)
− dhall-lang/tests/typecheck/success/prelude/Optional/filter/0B.dhall
@@ -1,1 +0,0 @@-Optional Natural
− dhall-lang/tests/typecheck/success/prelude/Optional/filter/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/filter Natural Natural/odd (Some 2)
− dhall-lang/tests/typecheck/success/prelude/Optional/filter/1B.dhall
@@ -1,1 +0,0 @@-Optional Natural
− dhall-lang/tests/typecheck/success/prelude/Optional/fold/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/fold Natural (Some 2) Natural (λ(x : Natural) → x) 0
− dhall-lang/tests/typecheck/success/prelude/Optional/fold/0B.dhall
@@ -1,1 +0,0 @@-Natural
− dhall-lang/tests/typecheck/success/prelude/Optional/fold/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/fold Natural (None Natural) Natural (λ(x : Natural) → x) 0
− dhall-lang/tests/typecheck/success/prelude/Optional/fold/1B.dhall
@@ -1,1 +0,0 @@-Natural
− dhall-lang/tests/typecheck/success/prelude/Optional/head/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/head Natural [ None Natural, Some 1, Some 2 ]
− dhall-lang/tests/typecheck/success/prelude/Optional/head/0B.dhall
@@ -1,1 +0,0 @@-Optional Natural
− dhall-lang/tests/typecheck/success/prelude/Optional/head/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/head Natural [ None Natural, None Natural ]
− dhall-lang/tests/typecheck/success/prelude/Optional/head/1B.dhall
@@ -1,1 +0,0 @@-Optional Natural
− dhall-lang/tests/typecheck/success/prelude/Optional/head/2A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/head Natural ([] : List (Optional Natural))
− dhall-lang/tests/typecheck/success/prelude/Optional/head/2B.dhall
@@ -1,1 +0,0 @@-Optional Natural
− dhall-lang/tests/typecheck/success/prelude/Optional/last/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/last Natural [ None Natural, Some 1, Some 2 ]
− dhall-lang/tests/typecheck/success/prelude/Optional/last/0B.dhall
@@ -1,1 +0,0 @@-Optional Natural
− dhall-lang/tests/typecheck/success/prelude/Optional/last/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/last Natural [ None Natural, None Natural ]
− dhall-lang/tests/typecheck/success/prelude/Optional/last/1B.dhall
@@ -1,1 +0,0 @@-Optional Natural
− dhall-lang/tests/typecheck/success/prelude/Optional/last/2A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/last Natural ([] : List (Optional Natural))
− dhall-lang/tests/typecheck/success/prelude/Optional/last/2B.dhall
@@ -1,1 +0,0 @@-Optional Natural
− dhall-lang/tests/typecheck/success/prelude/Optional/length/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/length Natural (Some 2)
− dhall-lang/tests/typecheck/success/prelude/Optional/length/0B.dhall
@@ -1,1 +0,0 @@-Natural
− dhall-lang/tests/typecheck/success/prelude/Optional/length/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/length Natural (None Natural)
− dhall-lang/tests/typecheck/success/prelude/Optional/length/1B.dhall
@@ -1,1 +0,0 @@-Natural
− dhall-lang/tests/typecheck/success/prelude/Optional/map/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/map Natural Bool Natural/even (Some 3)
− dhall-lang/tests/typecheck/success/prelude/Optional/map/0B.dhall
@@ -1,1 +0,0 @@-Optional Bool
− dhall-lang/tests/typecheck/success/prelude/Optional/map/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/map Natural Bool Natural/even (None Natural)
− dhall-lang/tests/typecheck/success/prelude/Optional/map/1B.dhall
@@ -1,1 +0,0 @@-Optional Bool
− dhall-lang/tests/typecheck/success/prelude/Optional/null/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/null Natural (Some 2)
− dhall-lang/tests/typecheck/success/prelude/Optional/null/0B.dhall
@@ -1,1 +0,0 @@-Bool
− dhall-lang/tests/typecheck/success/prelude/Optional/null/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/null Natural (None Natural)
− dhall-lang/tests/typecheck/success/prelude/Optional/null/1B.dhall
@@ -1,1 +0,0 @@-Bool
− dhall-lang/tests/typecheck/success/prelude/Optional/toList/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/toList Natural (Some 1)
− dhall-lang/tests/typecheck/success/prelude/Optional/toList/0B.dhall
@@ -1,1 +0,0 @@-List Natural
− dhall-lang/tests/typecheck/success/prelude/Optional/toList/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/toList Natural (None Natural)
− dhall-lang/tests/typecheck/success/prelude/Optional/toList/1B.dhall
@@ -1,1 +0,0 @@-List Natural
− dhall-lang/tests/typecheck/success/prelude/Optional/unzip/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/unzip Text Bool (Some { _1 = "ABC", _2 = True })
− dhall-lang/tests/typecheck/success/prelude/Optional/unzip/0B.dhall
@@ -1,1 +0,0 @@-{ _1 : Optional Text, _2 : Optional Bool }
− dhall-lang/tests/typecheck/success/prelude/Optional/unzip/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Optional/unzip Text Bool (None { _1 : Text, _2 : Bool })
− dhall-lang/tests/typecheck/success/prelude/Optional/unzip/1B.dhall
@@ -1,1 +0,0 @@-{ _1 : Optional Text, _2 : Optional Bool }
− dhall-lang/tests/typecheck/success/prelude/Text/concat/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Text/concat [ "ABC", "DEF", "GHI" ]
− dhall-lang/tests/typecheck/success/prelude/Text/concat/0B.dhall
@@ -1,1 +0,0 @@-Text
− dhall-lang/tests/typecheck/success/prelude/Text/concat/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Text/concat ([] : List Text)
− dhall-lang/tests/typecheck/success/prelude/Text/concat/1B.dhall
@@ -1,1 +0,0 @@-Text
− dhall-lang/tests/typecheck/success/prelude/Text/concatMap/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Text/concatMap Natural (λ(n : Natural) → "${Natural/show n} ") [ 0, 1, 2 ]
− dhall-lang/tests/typecheck/success/prelude/Text/concatMap/0B.dhall
@@ -1,1 +0,0 @@-Text
− dhall-lang/tests/typecheck/success/prelude/Text/concatMap/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Text/concatMap Natural (λ(n : Natural) → "${Natural/show n} ") ([] : List Natural)
− dhall-lang/tests/typecheck/success/prelude/Text/concatMap/1B.dhall
@@ -1,1 +0,0 @@-Text
− dhall-lang/tests/typecheck/success/prelude/Text/concatMapSep/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Text/concatMapSep ", " Natural Natural/show [ 0, 1, 2 ]
− dhall-lang/tests/typecheck/success/prelude/Text/concatMapSep/0B.dhall
@@ -1,1 +0,0 @@-Text
− dhall-lang/tests/typecheck/success/prelude/Text/concatMapSep/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Text/concatMapSep ", " Natural Natural/show ([] : List Natural)
− dhall-lang/tests/typecheck/success/prelude/Text/concatMapSep/1B.dhall
@@ -1,1 +0,0 @@-Text
− dhall-lang/tests/typecheck/success/prelude/Text/concatSep/0A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Text/concatSep ", " [ "ABC", "DEF", "GHI" ]
− dhall-lang/tests/typecheck/success/prelude/Text/concatSep/0B.dhall
@@ -1,1 +0,0 @@-Text
− dhall-lang/tests/typecheck/success/prelude/Text/concatSep/1A.dhall
@@ -1,1 +0,0 @@-../../../../../../Prelude/Text/concatSep ", " ([] : List Text)
− dhall-lang/tests/typecheck/success/prelude/Text/concatSep/1B.dhall
@@ -1,1 +0,0 @@-Text
− dhall-lang/tests/typecheck/success/recordOfRecordOfTypesA.dhall
@@ -1,5 +0,0 @@-let types = { Scopes = < Public | Private > }--let prelude = { types = types }--in  prelude.types.Scopes.Public
− dhall-lang/tests/typecheck/success/recordOfRecordOfTypesB.dhall
@@ -1,1 +0,0 @@-< Public | Private >
− dhall-lang/tests/typecheck/success/recordOfTypesA.dhall
@@ -1,1 +0,0 @@-{ x = Text, y = List }
− dhall-lang/tests/typecheck/success/recordOfTypesB.dhall
@@ -1,1 +0,0 @@-{ x : Type, y : Type → Type }
− dhall-lang/tests/typecheck/success/simple/access/0A.dhall
@@ -1,1 +0,0 @@-{ x = Text }.x
− dhall-lang/tests/typecheck/success/simple/access/0B.dhall
@@ -1,1 +0,0 @@-Type
− dhall-lang/tests/typecheck/success/simple/access/1A.dhall
@@ -1,1 +0,0 @@-< Foo : Text | Bar : Natural >.Foo
− dhall-lang/tests/typecheck/success/simple/access/1B.dhall
@@ -1,1 +0,0 @@-∀(Foo : Text) → < Bar : Natural | Foo : Text >
− dhall-lang/tests/typecheck/success/simple/anonymousFunctionsInTypesA.dhall
@@ -1,5 +0,0 @@-    let anonymousFunction = λ(a : Type) → List a--in    λ(HigherOrderType : (Type → Type) → Type)-    → λ(x : HigherOrderType anonymousFunction)-    → (x : HigherOrderType anonymousFunction)
− dhall-lang/tests/typecheck/success/simple/anonymousFunctionsInTypesB.dhall
@@ -1,4 +0,0 @@-  ∀(HigherOrderType : (Type → Type) → Type)-→ ∀(x : HigherOrderType (λ(a : Type) → List a))-→ HigherOrderType (λ(a : Type) → List a)-
− dhall-lang/tests/typecheck/success/simple/complexShadowingA.dhall
@@ -1,6 +0,0 @@-let x = Bool-let x = Natural-in  \(x: x@1 {- Bool -})- -> \(x: x@1 {- Natural -})- -> let x = if x@1 then 0 else 1-    in  (x + x@1) : x@3
− dhall-lang/tests/typecheck/success/simple/complexShadowingB.dhall
@@ -1,1 +0,0 @@-∀(x : Bool) → ∀(x : Natural) → Natural
− dhall-lang/tests/typecheck/success/simple/fieldsAreTypesA.dhall
@@ -1,1 +0,0 @@-{ x = Bool, y = Text, z = List }
− dhall-lang/tests/typecheck/success/simple/fieldsAreTypesB.dhall
@@ -1,1 +0,0 @@-{ x : Type, y : Type, z : Type → Type }
− dhall-lang/tests/typecheck/success/simple/kindParameterA.dhall
@@ -1,1 +0,0 @@-λ(k : Kind) → λ(a : k → k → Type) → λ(x : k) → a x
− dhall-lang/tests/typecheck/success/simple/kindParameterB.dhall
@@ -1,1 +0,0 @@-∀(k : Kind) → (k → k → Type) → k → k → Type
− dhall-lang/tests/typecheck/success/simple/mergeEquivalenceA.dhall
@@ -1,6 +0,0 @@-let Foo = < Bar : Natural | Baz : Natural >--in    λ(a : Type)-	→ λ(f : Natural → a)-	→ λ(ts : Foo)-	→ merge { Bar = λ(a : Natural) → f a, Baz = f } ts
− dhall-lang/tests/typecheck/success/simple/mergeEquivalenceB.dhall
@@ -1,1 +0,0 @@-∀(a : Type) → ∀(f : Natural → a) → ∀(ts : < Bar : Natural | Baz : Natural >) → a
− dhall-lang/tests/typecheck/success/simple/mixedFieldAccessA.dhall
@@ -1,9 +0,0 @@--- Verify that users can use `.` to both access a record field and a union--- constructor within the same expression.  This is a common idiom if a user--- provides a types package.--let Scope = < Public | Private >--let types = { Scope = Scope }--in  types.Scope.Public
− dhall-lang/tests/typecheck/success/simple/mixedFieldAccessB.dhall
@@ -1,1 +0,0 @@-< Private | Public >
− dhall-lang/tests/typecheck/success/simple/unionsOfTypesA.dhall
@@ -1,1 +0,0 @@-< Left : Type → Type | Right : Type >.Left List
− dhall-lang/tests/typecheck/success/simple/unionsOfTypesB.dhall
@@ -1,1 +0,0 @@-< Left : Type → Type | Right : Type >
dhall.cabal view
@@ -1,13 +1,12 @@+Cabal-Version: 2.4 Name: dhall-Version: 1.24.0-Cabal-Version: >=1.10+Version: 1.42.3 Build-Type: Simple-Tested-With: GHC == 7.10.3, 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,11 +21,13 @@     .     Read "Dhall.Tutorial" to learn how to use this library Category: Compiler+Data-Files:+    man/dhall.1 Extra-Source-Files:-    benchmark/deep-nested-large-record/*.dhall-    benchmark/examples/*.dhall-    benchmark/examples/normalize/*.dhall     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@@ -34,50 +35,105 @@     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/package.dhall-    dhall-lang/Prelude/Integer/package.dhall+    dhall-lang/Prelude/Function/identity+    dhall-lang/Prelude/Integer/abs+    dhall-lang/Prelude/Integer/add+    dhall-lang/Prelude/Integer/clamp+    dhall-lang/Prelude/Integer/equal+    dhall-lang/Prelude/Integer/greaterThan+    dhall-lang/Prelude/Integer/greaterThanEqual+    dhall-lang/Prelude/Integer/lessThan+    dhall-lang/Prelude/Integer/lessThanEqual+    dhall-lang/Prelude/Integer/multiply+    dhall-lang/Prelude/Integer/negate+    dhall-lang/Prelude/Integer/negative+    dhall-lang/Prelude/Integer/nonNegative+    dhall-lang/Prelude/Integer/nonPositive+    dhall-lang/Prelude/Integer/positive     dhall-lang/Prelude/Integer/show+    dhall-lang/Prelude/Integer/subtract     dhall-lang/Prelude/Integer/toDouble-    dhall-lang/Prelude/JSON/keyText-    dhall-lang/Prelude/JSON/keyValue+    dhall-lang/Prelude/Integer/toNatural+    dhall-lang/Prelude/JSON/Format     dhall-lang/Prelude/JSON/Nesting-    dhall-lang/Prelude/JSON/package.dhall     dhall-lang/Prelude/JSON/Tagged+    dhall-lang/Prelude/JSON/Type+    dhall-lang/Prelude/JSON/array+    dhall-lang/Prelude/JSON/bool+    dhall-lang/Prelude/JSON/double+    dhall-lang/Prelude/JSON/integer+    dhall-lang/Prelude/JSON/keyText+    dhall-lang/Prelude/JSON/keyValue+    dhall-lang/Prelude/JSON/natural+    dhall-lang/Prelude/JSON/null+    dhall-lang/Prelude/JSON/number+    dhall-lang/Prelude/JSON/object+    dhall-lang/Prelude/JSON/omitNullFields+    dhall-lang/Prelude/JSON/render+    dhall-lang/Prelude/JSON/renderAs+    dhall-lang/Prelude/JSON/renderYAML+    dhall-lang/Prelude/JSON/string+    dhall-lang/Prelude/JSON/tagInline+    dhall-lang/Prelude/JSON/tagNested     dhall-lang/Prelude/List/all     dhall-lang/Prelude/List/any     dhall-lang/Prelude/List/build     dhall-lang/Prelude/List/concat     dhall-lang/Prelude/List/concatMap+    dhall-lang/Prelude/List/default+    dhall-lang/Prelude/List/drop+    dhall-lang/Prelude/List/empty     dhall-lang/Prelude/List/filter     dhall-lang/Prelude/List/fold     dhall-lang/Prelude/List/generate     dhall-lang/Prelude/List/head+    dhall-lang/Prelude/List/index     dhall-lang/Prelude/List/indexed     dhall-lang/Prelude/List/iterate     dhall-lang/Prelude/List/last     dhall-lang/Prelude/List/length     dhall-lang/Prelude/List/map     dhall-lang/Prelude/List/null-    dhall-lang/Prelude/List/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/Map/Entry+    dhall-lang/Prelude/Map/Type+    dhall-lang/Prelude/Map/empty+    dhall-lang/Prelude/Map/keyText+    dhall-lang/Prelude/Map/keyValue+    dhall-lang/Prelude/Map/keys+    dhall-lang/Prelude/Map/map+    dhall-lang/Prelude/Map/values     dhall-lang/Prelude/Monoid     dhall-lang/Prelude/Natural/build     dhall-lang/Prelude/Natural/enumerate+    dhall-lang/Prelude/Natural/equal     dhall-lang/Prelude/Natural/even     dhall-lang/Prelude/Natural/fold+    dhall-lang/Prelude/Natural/greaterThan+    dhall-lang/Prelude/Natural/greaterThanEqual     dhall-lang/Prelude/Natural/isZero+    dhall-lang/Prelude/Natural/lessThan+    dhall-lang/Prelude/Natural/lessThanEqual+    dhall-lang/Prelude/Natural/listMax+    dhall-lang/Prelude/Natural/listMin+    dhall-lang/Prelude/Natural/max+    dhall-lang/Prelude/Natural/min     dhall-lang/Prelude/Natural/odd-    dhall-lang/Prelude/Natural/package.dhall     dhall-lang/Prelude/Natural/product     dhall-lang/Prelude/Natural/show+    dhall-lang/Prelude/Natural/sort+    dhall-lang/Prelude/Natural/subtract     dhall-lang/Prelude/Natural/sum     dhall-lang/Prelude/Natural/toDouble     dhall-lang/Prelude/Natural/toInteger@@ -85,6 +141,7 @@     dhall-lang/Prelude/Optional/any     dhall-lang/Prelude/Optional/build     dhall-lang/Prelude/Optional/concat+    dhall-lang/Prelude/Optional/default     dhall-lang/Prelude/Optional/filter     dhall-lang/Prelude/Optional/fold     dhall-lang/Prelude/Optional/head@@ -92,285 +149,34 @@     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/package.dhall     dhall-lang/Prelude/Text/concat     dhall-lang/Prelude/Text/concatMap     dhall-lang/Prelude/Text/concatMapSep     dhall-lang/Prelude/Text/concatSep-    dhall-lang/Prelude/Text/package.dhall+    dhall-lang/Prelude/Text/default+    dhall-lang/Prelude/Text/defaultMap+    dhall-lang/Prelude/Text/replicate     dhall-lang/Prelude/Text/show-    dhall-lang/tests/binary-decode/success/unit/*.dhall-    dhall-lang/tests/binary-decode/success/unit/*.dhallb-    dhall-lang/tests/import/data/*.txt-    dhall-lang/tests/import/data/*.dhall-    dhall-lang/tests/import/data/fieldOrder/*.dhall-    dhall-lang/tests/import/failure/*.dhall-    dhall-lang/tests/import/success/*.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/prelude/Bool/and/*.dhall-    dhall-lang/tests/normalization/success/prelude/Bool/and/*.dhall-    dhall-lang/tests/normalization/success/prelude/Bool/build/*.dhall-    dhall-lang/tests/normalization/success/prelude/Bool/build/*.dhall-    dhall-lang/tests/normalization/success/prelude/Bool/even/*.dhall-    dhall-lang/tests/normalization/success/prelude/Bool/even/*.dhall-    dhall-lang/tests/normalization/success/prelude/Bool/fold/*.dhall-    dhall-lang/tests/normalization/success/prelude/Bool/fold/*.dhall-    dhall-lang/tests/normalization/success/prelude/Bool/not/*.dhall-    dhall-lang/tests/normalization/success/prelude/Bool/not/*.dhall-    dhall-lang/tests/normalization/success/prelude/Bool/odd/*.dhall-    dhall-lang/tests/normalization/success/prelude/Bool/odd/*.dhall-    dhall-lang/tests/normalization/success/prelude/Bool/or/*.dhall-    dhall-lang/tests/normalization/success/prelude/Bool/or/*.dhall-    dhall-lang/tests/normalization/success/prelude/Bool/show/*.dhall-    dhall-lang/tests/normalization/success/prelude/Bool/show/*.dhall-    dhall-lang/tests/normalization/success/prelude/Double/show/*.dhall-    dhall-lang/tests/normalization/success/prelude/Double/show/*.dhall-    dhall-lang/tests/normalization/success/prelude/Integer/show/*.dhall-    dhall-lang/tests/normalization/success/prelude/Integer/show/*.dhall-    dhall-lang/tests/normalization/success/prelude/Integer/toDouble/*.dhall-    dhall-lang/tests/normalization/success/prelude/Integer/toDouble/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/all/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/all/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/any/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/any/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/build/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/build/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/concat/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/concat/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/concatMap/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/concatMap/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/filter/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/filter/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/fold/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/fold/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/generate/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/generate/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/head/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/head/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/indexed/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/indexed/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/iterate/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/iterate/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/last/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/last/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/length/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/length/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/map/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/map/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/null/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/null/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/replicate/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/replicate/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/reverse/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/reverse/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/shifted/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/shifted/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/unzip/*.dhall-    dhall-lang/tests/normalization/success/prelude/List/unzip/*.dhall-    dhall-lang/tests/normalization/success/prelude/Natural/build/*.dhall-    dhall-lang/tests/normalization/success/prelude/Natural/build/*.dhall-    dhall-lang/tests/normalization/success/prelude/Natural/enumerate/*.dhall-    dhall-lang/tests/normalization/success/prelude/Natural/enumerate/*.dhall-    dhall-lang/tests/normalization/success/prelude/Natural/even/*.dhall-    dhall-lang/tests/normalization/success/prelude/Natural/even/*.dhall-    dhall-lang/tests/normalization/success/prelude/Natural/fold/*.dhall-    dhall-lang/tests/normalization/success/prelude/Natural/fold/*.dhall-    dhall-lang/tests/normalization/success/prelude/Natural/isZero/*.dhall-    dhall-lang/tests/normalization/success/prelude/Natural/isZero/*.dhall-    dhall-lang/tests/normalization/success/prelude/Natural/odd/*.dhall-    dhall-lang/tests/normalization/success/prelude/Natural/odd/*.dhall-    dhall-lang/tests/normalization/success/prelude/Natural/product/*.dhall-    dhall-lang/tests/normalization/success/prelude/Natural/product/*.dhall-    dhall-lang/tests/normalization/success/prelude/Natural/show/*.dhall-    dhall-lang/tests/normalization/success/prelude/Natural/show/*.dhall-    dhall-lang/tests/normalization/success/prelude/Natural/sum/*.dhall-    dhall-lang/tests/normalization/success/prelude/Natural/sum/*.dhall-    dhall-lang/tests/normalization/success/prelude/Natural/toDouble/*.dhall-    dhall-lang/tests/normalization/success/prelude/Natural/toDouble/*.dhall-    dhall-lang/tests/normalization/success/prelude/Natural/toInteger/*.dhall-    dhall-lang/tests/normalization/success/prelude/Natural/toInteger/*.dhall-    dhall-lang/tests/normalization/success/prelude/Optional/all/*.dhall-    dhall-lang/tests/normalization/success/prelude/Optional/all/*.dhall-    dhall-lang/tests/normalization/success/prelude/Optional/any/*.dhall-    dhall-lang/tests/normalization/success/prelude/Optional/any/*.dhall-    dhall-lang/tests/normalization/success/prelude/Optional/build/*.dhall-    dhall-lang/tests/normalization/success/prelude/Optional/build/*.dhall-    dhall-lang/tests/normalization/success/prelude/Optional/concat/*.dhall-    dhall-lang/tests/normalization/success/prelude/Optional/concat/*.dhall-    dhall-lang/tests/normalization/success/prelude/Optional/filter/*.dhall-    dhall-lang/tests/normalization/success/prelude/Optional/filter/*.dhall-    dhall-lang/tests/normalization/success/prelude/Optional/fold/*.dhall-    dhall-lang/tests/normalization/success/prelude/Optional/fold/*.dhall-    dhall-lang/tests/normalization/success/prelude/Optional/head/*.dhall-    dhall-lang/tests/normalization/success/prelude/Optional/head/*.dhall-    dhall-lang/tests/normalization/success/prelude/Optional/last/*.dhall-    dhall-lang/tests/normalization/success/prelude/Optional/last/*.dhall-    dhall-lang/tests/normalization/success/prelude/Optional/length/*.dhall-    dhall-lang/tests/normalization/success/prelude/Optional/length/*.dhall-    dhall-lang/tests/normalization/success/prelude/Optional/map/*.dhall-    dhall-lang/tests/normalization/success/prelude/Optional/map/*.dhall-    dhall-lang/tests/normalization/success/prelude/Optional/null/*.dhall-    dhall-lang/tests/normalization/success/prelude/Optional/null/*.dhall-    dhall-lang/tests/normalization/success/prelude/Optional/toList/*.dhall-    dhall-lang/tests/normalization/success/prelude/Optional/toList/*.dhall-    dhall-lang/tests/normalization/success/prelude/Optional/unzip/*.dhall-    dhall-lang/tests/normalization/success/prelude/Optional/unzip/*.dhall-    dhall-lang/tests/normalization/success/prelude/Text/concat/*.dhall-    dhall-lang/tests/normalization/success/prelude/Text/concat/*.dhall-    dhall-lang/tests/normalization/success/prelude/Text/concatMap/*.dhall-    dhall-lang/tests/normalization/success/prelude/Text/concatMap/*.dhall-    dhall-lang/tests/normalization/success/prelude/Text/concatMapSep/*.dhall-    dhall-lang/tests/normalization/success/prelude/Text/concatMapSep/*.dhall-    dhall-lang/tests/normalization/success/prelude/Text/concatSep/*.dhall-    dhall-lang/tests/normalization/success/prelude/Text/concatSep/*.dhall-    dhall-lang/tests/normalization/success/prelude/Text/show/*.dhall-    dhall-lang/tests/normalization/success/prelude/Text/show/*.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/alpha-normalization/success/unit/*.dhall-    dhall-lang/tests/parser/failure/*.dhall-    dhall-lang/tests/parser/success/*.dhall-    dhall-lang/tests/parser/success/*.dhallb-    dhall-lang/tests/parser/success/unit/*.dhall-    dhall-lang/tests/parser/success/unit/*.dhallb-    dhall-lang/tests/parser/success/unit/import/*.dhall-    dhall-lang/tests/parser/success/unit/import/*.dhallb-    dhall-lang/tests/parser/success/text/*.dhall-    dhall-lang/tests/parser/success/text/*.dhallb-    dhall-lang/tests/typecheck/data/*.dhall-    dhall-lang/tests/typecheck/failure/*.dhall-    dhall-lang/tests/typecheck/success/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Bool/and/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Bool/and/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Bool/build/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Bool/build/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Bool/even/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Bool/even/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Bool/fold/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Bool/fold/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Bool/not/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Bool/not/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Bool/odd/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Bool/odd/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Bool/or/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Bool/or/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Bool/show/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Bool/show/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Double/show/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Double/show/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Integer/show/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Integer/show/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Integer/toDouble/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Integer/toDouble/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/all/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/all/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/any/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/any/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/build/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/build/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/concat/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/concat/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/concatMap/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/concatMap/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/filter/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/filter/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/fold/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/fold/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/generate/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/generate/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/head/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/head/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/indexed/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/indexed/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/iterate/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/iterate/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/last/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/last/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/length/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/length/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/map/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/map/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/null/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/null/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/replicate/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/replicate/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/reverse/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/reverse/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/shifted/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/shifted/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/unzip/*.dhall-    dhall-lang/tests/typecheck/success/prelude/List/unzip/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Monoid/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Natural/build/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Natural/build/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Natural/enumerate/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Natural/enumerate/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Natural/even/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Natural/even/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Natural/fold/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Natural/fold/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Natural/isZero/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Natural/isZero/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Natural/odd/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Natural/odd/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Natural/product/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Natural/product/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Natural/show/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Natural/show/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Natural/sum/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Natural/sum/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Natural/toDouble/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Natural/toDouble/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Natural/toInteger/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Natural/toInteger/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Optional/all/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Optional/all/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Optional/any/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Optional/any/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Optional/build/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Optional/build/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Optional/concat/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Optional/concat/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Optional/filter/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Optional/filter/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Optional/fold/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Optional/fold/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Optional/head/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Optional/head/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Optional/last/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Optional/last/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Optional/length/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Optional/length/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Optional/map/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Optional/map/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Optional/null/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Optional/null/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Optional/toList/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Optional/toList/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Optional/unzip/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Optional/unzip/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Text/concat/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Text/concat/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Text/concatMap/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Text/concatMap/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Text/concatMapSep/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Text/concatMapSep/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Text/concatSep/*.dhall-    dhall-lang/tests/typecheck/success/prelude/Text/concatSep/*.dhall-    dhall-lang/tests/typecheck/success/simple/access/*.dhall-    dhall-lang/tests/typecheck/success/simple/*.dhall-    tests/format/*.dhall-    tests/lint/success/*.dhall-    tests/regression/*.dhall-    tests/tutorial/*.dhall+    dhall-lang/Prelude/Text/spaces+    dhall-lang/Prelude/XML/Type+    dhall-lang/Prelude/XML/attribute+    dhall-lang/Prelude/XML/element+    dhall-lang/Prelude/XML/emptyAttributes+    dhall-lang/Prelude/XML/leaf+    dhall-lang/Prelude/XML/render+    dhall-lang/Prelude/XML/text+    dhall-lang/tests/**/*.dhall+    dhall-lang/tests/**/*.dhallb+    dhall-lang/tests/**/*.hash+    dhall-lang/tests/**/*.txt+    dhall-lang/tests/**/*.bin+    dhall-lang/tests/import/cache/dhall/12203871180b87ecaba8b53fffb2a8b52d3fce98098fab09a6f759358b9e8042eedc+    dhall-lang/tests/import/cache/dhall/1220618f785ce8f3930a9144398f576f0a992544b51212bc9108c31b4e670dc6ed21+    tests/**/*.dhall+    tests/**/*.tags+    tests/**/*.txt  Source-Repository head     Type: git@@ -381,61 +187,112 @@   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.8.2.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.10,-        bytestring                                 < 0.11,+        ansi-terminal               >= 0.6.3.1  && < 1.2 ,+        atomic-write                >= 0.2.0.7  && < 0.3 ,+        base16-bytestring           >= 1.0.0.0           ,+        bytestring                                 < 0.13,         case-insensitive                           < 1.3 ,         cborg                       >= 0.2.0.0  && < 0.3 ,-        cborg-json                                 < 0.3 ,-        containers                  >= 0.5.0.0  && < 0.7 ,+        cborg-json                  >= 0.2.2.0  && < 0.3 ,+        containers                  >= 0.5.8.0  && < 0.9 ,         contravariant                              < 1.6 ,-        cryptonite                  >= 0.23     && < 1.0 ,-        Diff                        >= 0.2      && < 0.4 ,-        directory                   >= 1.2.2.0  && < 1.4 ,+        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 ,-        haskeline                   >= 0.7.2.1  && < 0.8 ,-        lens-family-core            >= 1.0.0    && < 1.3 ,-        megaparsec                  >= 6.5.0    && < 7.1 ,-        memory                      >= 0.14     && < 0.15,-        mtl                         >= 2.2.1    && < 2.3 ,-        optparse-applicative        >= 0.14.0.0 && < 0.15,+        filepath                    >= 1.4      && < 1.6 ,+        half                        >= 0.2.2.3  && < 0.4 ,+        haskeline                   >= 0.7.2.1  && < 0.9 ,+        hashable                    >= 1.2      && < 1.6 ,+        indexed-traversable                        < 0.2 ,+        microlens                   >= 0.4.14.0 && < 0.5 ,+        microlens-mtl               >= 0.1      && < 0.3 ,+        -- megaparsec follows SemVer: https://github.com/mrkkrp/megaparsec/issues/469#issuecomment-927918469+        megaparsec                  >= 8        && < 10  ,+        mmorph                                     < 1.3 ,+        mtl                         >= 2.2.1    && < 2.4 ,+        network-uri                 >= 2.6      && < 2.7 ,+        optparse-applicative        >= 0.14.0.0 && < 0.20,         parsers                     >= 0.12.4   && < 0.13,-        prettyprinter               >= 1.2.0.1  && < 1.3 ,-        prettyprinter-ansi-terminal >= 1.1.1    && < 1.2 ,-        profunctors                 >= 3.1.2    && < 5.5 ,-        repline                     >= 0.2.1.0  && < 0.3 ,+        parser-combinators                               ,+        prettyprinter               >= 1.7.0    && < 1.8 ,+        prettyprinter-ansi-terminal >= 1.1.2    && < 1.2 ,+        pretty-simple                              < 4.2 ,+        repline                     >= 0.4.0.0  && < 0.5 ,         serialise                   >= 0.2.0.0  && < 0.3 ,         scientific                  >= 0.3.0.0  && < 0.4 ,-        template-haskell                           < 2.15,-        text                        >= 0.11.1.0 && < 1.3 ,-        transformers                >= 0.2.0.0  && < 0.6 ,-        transformers-compat         >= 0.6.2    && < 0.7 ,+        template-haskell            >= 2.13.0.0 && < 2.24,+        text                        >= 0.11.1.0 && < 2.2 ,+        text-manipulate             >= 0.2.0.1  && < 0.4 ,+        text-short                  >= 0.1      && < 0.2 ,+        th-lift-instances           >= 0.1.13   && < 0.2 ,+        time                        >= 1.9      && < 1.15,+        transformers                >= 0.5.2.0  && < 0.7 ,+        unix-compat                 >= 0.4.2    && < 0.8 ,         unordered-containers        >= 0.1.3.0  && < 0.3 ,-        uri-encode                                 < 1.6 ,-        vector                      >= 0.11.0.0 && < 0.13-    if flag(with-http)+        vector                      >= 0.11.0.0 && < 0.14++    if !os(windows)       Build-Depends:-        http-types                  >= 0.7.0    && < 0.13,-        http-client                 >= 0.4.30   && < 0.7 ,-        http-client-tls             >= 0.2.0    && < 0.4-    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.*+        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)-      Build-Depends: ghcjs-xhr+      Hs-Source-Dirs: ghcjs-src+      Build-Depends:+        ghcjs-base ,+        ghcjs-xhr+    else+      Hs-Source-Dirs: ghc-src+      Build-Depends:+        cryptohash-sha256+      if flag(with-http)+        Build-Depends:+          http-types                  >= 0.7.0    && < 0.13,+          http-client                 >= 0.5.0    && < 0.8+        if flag(use-http-client-tls)+          Build-Depends:+            http-client-tls           >= 0.2.0    && < 0.4      Other-Extensions:         BangPatterns@@ -466,157 +323,175 @@             TemplateHaskell      Exposed-Modules:-        Dhall,-        Dhall.Binary,-        Dhall.Context,-        Dhall.Core,-        Dhall.Diff,-        Dhall.Format,-        Dhall.Freeze,-        Dhall.Hash,-        Dhall.Import,-        Dhall.Lint,-        Dhall.Main,-        Dhall.Map,-        Dhall.Optics,-        Dhall.Set,-        Dhall.Src,-        Dhall.Parser,-        Dhall.Pretty,-        Dhall.Repl,-        Dhall.Tutorial,+        Dhall+        Dhall.Binary+        Dhall.Context+        Dhall.Core+        Dhall.Crypto+        Dhall.Diff+        Dhall.DirectoryTree+        Dhall.Format+        Dhall.Freeze+        Dhall.Import+        Dhall.Lint+        Dhall.Main+        Dhall.Marshal.Decode+        Dhall.Marshal.Encode+        Dhall.Map+        Dhall.Optics+        Dhall.Package+        Dhall.Parser+        Dhall.Parser.Expression+        Dhall.Parser.Token+        Dhall.Pretty+        Dhall.Repl+        Dhall.Schemas+        Dhall.Set+        Dhall.Src+        Dhall.Substitution+        Dhall.Tags+        Dhall.Tutorial         Dhall.TypeCheck+        Dhall.Util+        Dhall.Version     if !flag(cross)         Exposed-Modules:             Dhall.TH+    if impl(ghc >= 8.6.1)+        Exposed-Modules:+          Dhall.Deriving     Other-Modules:-        Dhall.Pretty.Internal,-        Dhall.Parser.Expression,-        Dhall.Parser.Combinators,-        Dhall.Parser.Token,-        Dhall.Import.Types,-        Dhall.Eval,-        Dhall.Util,+        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:+        Paths_dhall     if flag(with-http)       Other-Modules:         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.Tutorial-        Dhall.Test.TypeCheck+        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                                     ,-        deepseq                   >= 1.2.0.1  && < 1.5 ,         dhall                                          ,-        directory                                      ,-        filepath                                       ,         foldl                                    < 1.5 ,-        megaparsec                                     ,-        prettyprinter                                  ,-        QuickCheck                >= 2.10     && < 2.14,+        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 ,-        serialise                                      ,-        tasty                     >= 0.11.2   && < 1.3 ,-        tasty-hunit               >= 0.9.2    && < 0.11,-        tasty-quickcheck          >= 0.9.2    && < 0.11,-        text                      >= 0.11.1.0 && < 1.3 ,-        transformers                                   ,-        turtle                                   < 1.6 ,-        vector                    >= 0.11.0.0 && < 0.13+        special-values                           < 0.2 ,+        spoon                                    < 0.4 ,+        tasty                     >= 0.11.2   && < 1.6 ,+        tasty-expected-failure                   < 0.13,+        tasty-hunit               >= 0.10     && < 0.11,+        tasty-quickcheck          >= 0.9.2    && < 0.12,+        tasty-silver                             < 3.4 ,+        temporary                 >= 1.2.1    && < 1.4 ,+        turtle                    >= 1.6      && < 1.7 ,     Default-Language: Haskell2010  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,-        criterion                 >= 1.1      && < 1.6,         dhall                                         ,-        directory                                     ,-        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,-        criterion                 >= 1.1      && < 1.6,-        dhall-    Default-Language: Haskell2010--Benchmark dhall-command-    Type: exitcode-stdio-1.0-    Main-Is: Main.hs-    Hs-Source-Dirs: benchmark/dhall-command-    Build-Depends:-        base                      >= 4        && < 5  ,-        dhall-    Default-Language: Haskell2010-    ghc-options: -rtsopts -O2--Benchmark map-operations-    Type: exitcode-stdio-1.0-    Main-Is: Main.hs-    Hs-Source-Dirs: benchmark/map-    Build-Depends:-        base                      >= 4        && < 5  ,-        criterion                 >= 1.1      && < 1.6,-        dhall+        dhall                                         ,+        tasty-bench               >= 0.4      && < 0.5,     Default-Language: Haskell2010-    ghc-options: -rtsopts -O2
doctest/Main.hs view
@@ -1,33 +1,59 @@-module Main where+{-# LANGUAGE CPP #-} -import Data.Monoid ((<>))+module Main (main) where+ import System.FilePath ((</>))  import qualified GHC.IO.Encoding import qualified System.Directory+import qualified System.Environment import qualified System.IO-import qualified Test.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" "λ(n : Bool) → [ n && True, n && False, n || True, n || False ]"+        writeFile "makeBools.dhall" "λ(n : Bool) → [ n && True, n && False, n || True, n || False ]"         writeFile "bool1" "True"         writeFile "bool2" "False"         writeFile "both" "./bool1 && ./bool2"         writeFile "file2" "./file1"         writeFile "file1" "./file2"+        writeFile "simon.dhall" $ unlines+          [ "let Name = Text"+          , "let Font = < Arial | `Comic Sans` | Helvetica | `Times New Roman` >"+          , "let Person = { name : Name, favoriteFont : Font }"+          , "in  { name = \"Simon\", favoriteFont = Font.`Comic Sans` } : Person"+          ] -        Test.DocTest.doctest-            [ "--fast"-            , "-i" <> (prefix </> "src")-            , prefix </> "src/Dhall.hs"-            , prefix </> "src/Dhall/Import.hs"-            , prefix </> "src/Dhall/Tutorial.hs"+        Test.DocTest.doctest $+            [ "-DWITH_HTTP"+            , "-DUSE_HTTP_CLIENT_TLS"+            , "--fast"+            ] <> args <>+            [ prefix </> "ghc-src"++            -- Unfortunately we cannot target the entire @src@ directory.+            -- The reason is that src/Dhall/Version.hs depends on+            -- the generated Paths_dhall module which is "out-of-scope"+            -- when running the testsuite with cabal v1-test.+            -- Instead, we target a selection of modules whose combined module+            -- dependency tree covers all modules that contain doctests.++            -- , src+            , "-i" <> src+#if __GLASGOW_HASKELL__ >= 806+            , src </> "Dhall/Deriving.hs"+#endif+            , src </> "Dhall/Tags.hs"+            , src </> "Dhall/Tutorial.hs"             ]
+ ghc-src/Dhall/Crypto.hs view
@@ -0,0 +1,47 @@+{-# LANGUAGE DeriveDataTypeable         #-}+{-# LANGUAGE DeriveGeneric              #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}++{-| This module provides implementations of cryptographic utilities that only+    work for GHC (as opposed to GHCJS)+-}++module Dhall.Crypto (+      SHA256Digest(..)+    , sha256DigestFromByteString+    , sha256Hash+    , toString+    ) where++import Control.DeepSeq         (NFData)+import Data.ByteString         (ByteString)+import Data.Data               (Data)+import GHC.Generics            (Generic)++import qualified Crypto.Hash.SHA256+import qualified Data.ByteString        as ByteString+import qualified Data.ByteString.Base16 as Base16+import qualified Data.ByteString.Char8  as ByteString.Char8++-- | A SHA256 digest+newtype SHA256Digest = SHA256Digest { unSHA256Digest :: ByteString }+  deriving (Data, Eq, Generic, Ord, NFData)++instance Show SHA256Digest where+  show = toString++{-| Attempt to interpret a `ByteString` as a `SHA256Digest`, returning+    `Nothing` if the conversion fails+-}+sha256DigestFromByteString :: ByteString -> Maybe SHA256Digest+sha256DigestFromByteString bytes+  | ByteString.length bytes == 32 = Just (SHA256Digest bytes)+  | otherwise                     = Nothing++-- | Hash a `ByteString` and return the hash as a `SHA256Digest`+sha256Hash :: ByteString -> SHA256Digest+sha256Hash = SHA256Digest . Crypto.Hash.SHA256.hash++-- | 'String' representation of a 'SHA256Digest'+toString :: SHA256Digest -> String+toString (SHA256Digest bytes) = ByteString.Char8.unpack $ Base16.encode bytes
+ ghc-src/Dhall/Import/HTTP.hs view
@@ -0,0 +1,320 @@+{-# LANGUAGE NamedFieldPuns    #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards   #-}++module Dhall.Import.HTTP+    ( fetchFromHttpUrl+    , fetchFromHttpUrlBytes+    , originHeadersFileExpr+    ) where++import Control.Exception                (Exception)+import Control.Monad.IO.Class           (MonadIO (..))+import Control.Monad.Trans.State.Strict (StateT)+import Data.ByteString                  (ByteString)+import Data.CaseInsensitive             (CI)+import Data.Dynamic                     (toDyn)+import Data.List.NonEmpty               (NonEmpty (..))+import Data.Text.Encoding               (decodeUtf8)+import Dhall.Core+    ( Expr (..)+    , Directory (..)+    , File (..)+    , FilePrefix (..)+    , Import (..)+    , ImportHashed (..)+    , ImportMode (..)+    , ImportType (..)+    , Scheme (..)+    , URL (..)+    )+import Dhall.Import.Types+import Dhall.Parser                     (Src)+import Dhall.URL                        (renderURL)+import System.Directory                 (getXdgDirectory, XdgDirectory(XdgConfig))+import System.FilePath                  (splitDirectories)+++import Network.HTTP.Client (HttpException (..), HttpExceptionContent (..))++import qualified Control.Exception+import qualified Control.Monad.Trans.State.Strict as State+import qualified Data.ByteString.Lazy             as ByteString.Lazy+import qualified Data.HashMap.Strict              as HashMap+import qualified Data.Text                        as Text+import qualified Data.Text.Encoding+import qualified Dhall.Util+import qualified Network.HTTP.Client              as HTTP+import qualified Network.HTTP.Types++mkPrettyHttpException :: String -> HttpException -> PrettyHttpException+mkPrettyHttpException url ex =+    PrettyHttpException (renderPrettyHttpException url ex) (toDyn ex)++renderPrettyHttpException :: String -> HttpException -> String+renderPrettyHttpException _ (InvalidUrlException _ r) =+      "\n"+  <>  "\ESC[1;31mError\ESC[0m: Invalid URL\n"+  <>  "\n"+  <>  "URL: " <> show r <> "\n"+renderPrettyHttpException url (HttpExceptionRequest _ e) =+  case e of+    ConnectionFailure _ ->+          "\n"+      <>  "\ESC[1;31mError\ESC[0m: Remote host not found\n"+      <>  "\n"+      <>  "URL: " <> url <> "\n"+    InvalidDestinationHost host ->+          "\n"+      <>  "\ESC[1;31mError\ESC[0m: Invalid remote host name:\n"+      <>  "\n"+      <>  "Host: " <> show host <> "\n"+    ResponseTimeout ->+          "\n"+      <>  "\ESC[1;31mError\ESC[0m: The remote host took too long to respond\n"+      <>  "\n"+      <>  "URL: " <> url <> "\n"+    ConnectionTimeout ->+          "\n"+      <>  "\ESC[1;31mError\ESC[0m: Connection establishment took too long\n"+      <>  "\n"+      <>  "URL: " <> url <> "\n"+    StatusCodeException response body -> prefix <> suffix+      where+        prefix+            | statusCode == 401 =+                    "\n"+                <>  "\ESC[1;31mError\ESC[0m: Access unauthorized\n"+            | statusCode == 403 =+                    "\n"+                <>  "\ESC[1;31mError\ESC[0m: Access forbidden\n"+            | statusCode == 404 =+                    "\n"+                <>  "\ESC[1;31mError\ESC[0m: Remote file not found\n"+            | statusCode == 500 =+                    "\n"+                <>  "\ESC[1;31mError\ESC[0m: Server-side failure\n"+            | statusCode == 502 =+                    "\n"+                <>  "\ESC[1;31mError\ESC[0m: Upstream failure\n"+            | statusCode == 503 =+                    "\n"+                <>  "\ESC[1;31mError\ESC[0m: Server temporarily unavailable\n"+            | statusCode == 504 =+                    "\n"+                <>  "\ESC[1;31mError\ESC[0m: Upstream timeout\n"+            | otherwise =+                    "\n"+                <>  "\ESC[1;31mError\ESC[0m: HTTP request failure\n"++        suffix =+                "\n"+            <>  "HTTP status code: " <> show statusCode <> "\n"+            <>  "\n"+            <>  "URL: " <> url <> "\n"+            <>  message++        statusCode =+            Network.HTTP.Types.statusCode+                (HTTP.responseStatus response)++        message =+            case Data.Text.Encoding.decodeUtf8' body of+                Left _ ->+                        "\n"+                    <>  "Message (non-UTF8 bytes):\n"+                    <>  "\n"+                    <>  truncatedBodyString <> "\n"+                  where+                    bodyString = show body++                    dots = "…"++                    truncatedLength = 80 - length dots++                    truncatedBodyString+                        | truncatedLength < length bodyString =+                            take truncatedLength bodyString <> dots+                        | otherwise =+                            bodyString+                Right "" ->+                    ""+                Right bodyText ->+                        "\n"+                    <>  "Message:\n"+                    <>  "\n"+                    <>  Text.unpack prefixedText+                  where+                    prefixedLines =+                        zipWith combine prefixes (Text.lines bodyText)+                      where+                        prefixes =+                            map (Text.pack . show) [(1 ::Int)..7] ++ [ "…" ]++                        combine n line = n <> "│ " <> line++                    prefixedText = Text.unlines prefixedLines++    e' -> "\n"+      <>  "\ESC[1;31mError\ESC[0m: " <> show e'+      <>  "\n"+      <>  "URL: " <> url <> "\n"++newManager :: StateT Status IO Manager+newManager = do+    Status { _manager = oldManager, ..} <- State.get++    case oldManager of+        Nothing -> do+            manager <- liftIO _newManager++            State.put (Status { _manager = Just manager , ..})++            return manager++        Just manager ->+            return manager++data NotCORSCompliant = NotCORSCompliant+    { expectedOrigins :: [ByteString]+    , actualOrigin    :: ByteString+    }++instance Exception NotCORSCompliant++instance Show NotCORSCompliant where+    show (NotCORSCompliant {..}) =+            Dhall.Util._ERROR <> ": Not CORS compliant\n"+        <>  "\n"+        <>  "Dhall supports transitive imports, meaning that an imported expression can\n"+        <>  "import other expressions.  However, a remote import (the \"parent\" import)\n"+        <>  "cannot import another remote import (the \"child\" import) unless the child\n"+        <>  "import grants permission to do using CORS.  The child import must respond with\n"+        <>  "an `Access-Control-Allow-Origin` response header that matches the parent\n"+        <>  "import, otherwise Dhall rejects the import.\n"+        <>  "\n" <> prologue+      where+        prologue =+            case expectedOrigins of+                [ expectedOrigin ] ->+                        "The following parent import:\n"+                    <>  "\n"+                    <>  "↳ " <> show actualOrigin <> "\n"+                    <>  "\n"+                    <>  "... did not match the expected origin:\n"+                    <>  "\n"+                    <>  "↳ " <> show expectedOrigin <> "\n"+                    <>  "\n"+                    <>  "... so import resolution failed.\n"+                [] ->+                        "The child response did not include any `Access-Control-Allow-Origin` header,\n"+                    <>  "so import resolution failed.\n"+                _:_:_ ->+                        "The child response included more than one `Access-Control-Allow-Origin` header,\n"+                    <>  "when only one such header should have been present, so import resolution\n"+                    <>  "failed.\n"+                    <>  "\n"+                    <>  "This may indicate that the server for the child import is misconfigured.\n"++corsCompliant+    :: MonadIO io+    => ImportType -> URL -> [(CI ByteString, ByteString)] -> io ()+corsCompliant (Remote parentURL) childURL responseHeaders = liftIO $ do+    let toOrigin (URL {..}) =+            Data.Text.Encoding.encodeUtf8 (prefix <> "://" <> authority)+          where+            prefix =+                case scheme of+                    HTTP  -> "http"+                    HTTPS -> "https"++    let actualOrigin = toOrigin parentURL++    let childOrigin = toOrigin childURL++    let predicate (header, _) = header == "Access-Control-Allow-Origin"++    let originHeaders = filter predicate responseHeaders++    let expectedOrigins = map snd originHeaders++    case expectedOrigins of+        [expectedOrigin]+            | expectedOrigin == "*" ->+                return ()+            | expectedOrigin == actualOrigin ->+                return ()+        _   | actualOrigin == childOrigin ->+                return ()+            | otherwise ->+                Control.Exception.throwIO (NotCORSCompliant {..})+corsCompliant _ _ _ = return ()++addHeaders :: OriginHeaders -> Maybe [HTTPHeader] -> HTTP.Request -> HTTP.Request+addHeaders originHeaders urlHeaders request =+    request { HTTP.requestHeaders = (filterHeaders urlHeaders) <> perOriginHeaders }+      where+        origin = decodeUtf8 (HTTP.host request) <> ":" <> Text.pack (show (HTTP.port request))+ +        perOriginHeaders = HashMap.lookupDefault [] origin originHeaders++        filterHeaders = foldMap (filter (not . overridden))++        overridden :: HTTPHeader -> Bool+        overridden (key, _value) = any (matchesKey key) perOriginHeaders++        matchesKey :: CI ByteString -> HTTPHeader -> Bool+        matchesKey key (candidate, _value) = key == candidate++fetchFromHttpUrlBytes+    :: URL -> Maybe [HTTPHeader] -> StateT Status IO ByteString+fetchFromHttpUrlBytes childURL mheaders = do+    Status { _loadOriginHeaders } <- State.get++    originHeaders <- _loadOriginHeaders++    manager <- newManager++    let childURLString = Text.unpack (renderURL childURL)++    baseRequest <- liftIO (HTTP.parseUrlThrow childURLString)++    let requestWithHeaders = addHeaders originHeaders mheaders baseRequest++    let io = HTTP.httpLbs requestWithHeaders manager++    let handler e = do+            let _ = e :: HttpException+            Control.Exception.throwIO (mkPrettyHttpException childURLString e)++    response <- liftIO (Control.Exception.handle handler io)++    Status {..} <- State.get++    case _stack of+        -- We ignore the first import in the stack since that is the same import+        -- as the `childUrl`+        _ :| Chained parentImport : _ -> do+            let parentImportType = importType (importHashed parentImport)++            corsCompliant parentImportType childURL (HTTP.responseHeaders response)+        _ -> do+            return ()++    return (ByteString.Lazy.toStrict (HTTP.responseBody response))++fetchFromHttpUrl :: URL -> Maybe [HTTPHeader] -> StateT Status IO Text.Text+fetchFromHttpUrl childURL mheaders = do+    bytes <- fetchFromHttpUrlBytes childURL mheaders++    case Data.Text.Encoding.decodeUtf8' bytes of+        Left  err  -> liftIO (Control.Exception.throwIO err)+        Right text -> return text++originHeadersFileExpr :: IO (Expr Src Import)+originHeadersFileExpr = do+    directoryStr <- getXdgDirectory XdgConfig "dhall"+    let components = map Text.pack (splitDirectories directoryStr)+    let directory = Directory (reverse components)+    let file = (File directory "headers.dhall")+    return (Embed (Import (ImportHashed Nothing (Local Absolute file)) Code))
+ ghc-src/Dhall/Import/Manager.hs view
@@ -0,0 +1,33 @@+{-# LANGUAGE CPP #-}++{-| Both the GHC and GHCJS implementations of 'Dhall.Import.Manager.Manager'+    export a `Dhall.Import.Manager.Manager` type suitable for use within the+    "Dhall.Import" module++    For the GHC implementation the `Dhall.Import.Manager` type is a real+    `Network.HTTP.Client.Manager` from the @http-client@ package.  For the+    GHCJS implementation the `Dhall.Import.Manager.Manager` type is+    a synonym for @`Data.Void.Void`@ since GHCJS does not use a+    `Network.HTTP.Client.Manager` for HTTP requests.+-}+module Dhall.Import.Manager+    ( -- * Manager+      Manager+    , defaultNewManager+    ) where++import           Network.HTTP.Client (Manager, newManager)+import qualified Network.HTTP.Client as HTTP++#ifdef USE_HTTP_CLIENT_TLS+import Network.HTTP.Client.TLS (tlsManagerSettings)+#endif++defaultNewManager :: IO Manager+defaultNewManager = newManager+#ifdef USE_HTTP_CLIENT_TLS+  tlsManagerSettings+#else+  HTTP.defaultManagerSettings+#endif+    { HTTP.managerResponseTimeout = HTTP.responseTimeoutMicro (30 * 1000 * 1000) }  -- 30 seconds
+ ghcjs-src/Dhall/Crypto.hs view
@@ -0,0 +1,75 @@+{-# LANGUAGE DeriveDataTypeable         #-}+{-# LANGUAGE DeriveGeneric              #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE JavaScriptFFI              #-}++{-| This module provides implementations of cryptographic utilities that only+    work for GHCJS+-}++module Dhall.Crypto (+      SHA256Digest(..)+    , sha256DigestFromByteString+    , sha256Hash+    ) where++import Control.DeepSeq                   (NFData)+import Data.ByteString                   (ByteString)+import Data.Data                         (Data)+import GHC.Generics                      (Generic)+import JavaScript.TypedArray.ArrayBuffer (ArrayBuffer)+import System.IO.Unsafe                  (unsafePerformIO)++import qualified Data.ByteString        as ByteString+import qualified Data.ByteString.Base16 as Base16+import qualified Data.ByteString.Char8  as ByteString.Char8+import qualified GHCJS.Buffer           as Buffer++-- | A SHA256 digest+newtype SHA256Digest = SHA256Digest { unSHA256Digest :: ByteString }+  deriving (Data, Eq, Generic, Ord, NFData)++instance Show SHA256Digest where+  show (SHA256Digest bytes) = ByteString.Char8.unpack $ Base16.encode bytes++{-| Attempt to interpret a `ByteString` as a `SHA256Digest`, returning+    `Nothing` if the conversion fails+-}+sha256DigestFromByteString :: ByteString -> Maybe SHA256Digest+sha256DigestFromByteString bytes+  | ByteString.length bytes == 32 = Just (SHA256Digest bytes)+  | otherwise                     = Nothing++-- Use NodeJS' crypto module if there's a 'process' module, e.g. we're running+-- inside GHCJS' THRunner. If we're running in the browser, use the WebCrypto+-- interface.+foreign import javascript interruptible+  "if (typeof process === 'undefined') { \+  \  crypto.subtle.digest('SHA-256', $1).then($c) \+  \} else { \+  \  $c(require('crypto').createHash('sha256').update(Buffer.from($1)).digest().buffer) \+  \}"+  js_sha256Hash :: ArrayBuffer -> IO ArrayBuffer++byteStringToArrayBuffer :: ByteString -> ArrayBuffer+byteStringToArrayBuffer b =+  js_arrayBufferSlice offset len $ Buffer.getArrayBuffer buffer+  where+    (buffer, offset, len) = Buffer.fromByteString b++foreign import javascript unsafe "$3.slice($1, $1 + $2)"+  js_arrayBufferSlice :: Int -> Int -> ArrayBuffer -> ArrayBuffer++arrayBufferToByteString :: ArrayBuffer -> ByteString+arrayBufferToByteString =+  Buffer.toByteString 0 Nothing . Buffer.createFromArrayBuffer++-- | Hash a `ByteString` and return the hash as a `SHA256Digest`+sha256Hash :: ByteString -> SHA256Digest+sha256Hash bytes+  | ByteString.length out == 32 = SHA256Digest out+  | otherwise = error "sha256Hash: didn't produce 32 bytes"+  where+    out =+      arrayBufferToByteString $+      unsafePerformIO $ js_sha256Hash (byteStringToArrayBuffer bytes)
+ ghcjs-src/Dhall/Import/HTTP.hs view
@@ -0,0 +1,52 @@+{-# LANGUAGE OverloadedStrings #-}++module Dhall.Import.HTTP+    ( fetchFromHttpUrl+    , fetchFromHttpUrlBytes+    , originHeadersFileExpr+    ) where++import Control.Monad.IO.Class           (MonadIO (..))+import Control.Monad.Trans.State.Strict (StateT)+import Data.ByteString                  (ByteString)+import Data.CaseInsensitive             (CI)+import Dhall.Core                       (URL (..), Expr (..))+import Dhall.Import.Types               (Import, Status)+import Dhall.Parser                     (Src)+import Dhall.URL                        (renderURL)++import qualified Data.Text          as Text+import qualified Data.Text.Encoding as Text.Encoding+import qualified JavaScript.XHR++fetchFromHttpUrl+    :: URL+    -> Maybe [(CI ByteString, ByteString)]+    -> StateT Status IO Text.Text+fetchFromHttpUrl childURL Nothing = do+    let childURLText = renderURL childURL++    let childURLString = Text.unpack childURLText++    -- No need to add a CORS compliance check when using GHCJS.  The browser+    -- will already check the CORS compliance of the following XHR+    (statusCode, body) <- liftIO (JavaScript.XHR.get childURLText)++    case statusCode of+        200 -> return ()+        _   -> fail (childURLString <> " returned a non-200 status code: " <> show statusCode)++    return body+fetchFromHttpUrl _ _ =+    fail "Dhall does not yet support custom headers when built using GHCJS"++fetchFromHTTPUrlBytes+    :: URL+    -> Maybe [(CI ByteString, ByteString)]+    -> StateT Status IO ByteString+fetchFromHTTPUrlBytes childUrl mheader = do+    text <- fetchFromHTTPUrl childUrl mheader+    return (Text.Encoding.encodeUtf8 text)++originHeadersFileExpr :: IO (Expr Src Import)+originHeadersFileExpr = return Missing
+ ghcjs-src/Dhall/Import/Manager.hs view
@@ -0,0 +1,26 @@+{-| Both the GHC and GHCJS implementations of `Dhall.Import.Manager.Manager`+    export a `Dhall.Import.Manager.Manager` type suitable for use within the+    "Dhall.Import" module++    For the GHC implementation the `Dhall.Import.Manager.Manager` type is a real+    `Network.HTTP.Client.Manager` from the @http-client@ package.  For the GHCJS+    implementation the `Dhall.Import.Manager.Manager` type is a synonym for+    @`Data.Void.Void`@ since GHCJS does not use a+    `Network.HTTP.Client.Manager` for HTTP requests.+-}+module Dhall.Import.Manager+    ( -- * Manager+      Manager+    , defaultNewManager+    ) where++{-| The GHCJS implementation does not require a `Network.HTTP.Client.Manager`++    The purpose of this synonym is so that "Dhall.Import.Types" can import a+    `Dhall.Import.Manager.Manager` type from "Dhall.Import.HTTP" that does the+    correct thing for both the GHC and GHCJS implementations+-}+type Manager = ()++defaultNewManager :: IO Manager+defaultNewManager = pure ()
+ man/dhall.1 view
@@ -0,0 +1,100 @@+.\" Automatically generated by Pandoc 2.9.2+.\"+.TH "dhall (1)" "" "" "" ""+.hy+.SH NAME+.PP+dhall - a programmable configuration language+.SH DESCRIPTION+.PP+\f[B]dhall\f[R] is the command-line interface to the Dhall language+.SH SYNOPSIS+.PP+dhall --file check.dhall+.PP+dhall --file error.dhall --explain+.PP+dhall hash --file to-hash.dhall+.PP+dhall freeze --file with-imports.dhall+.PP+dhall repl+.PP+dhall diff \[aq]./file1.dhall\[cq] \[aq]./file2.dhall\[cq]+.PP+dhall type --quiet --file check-ci.dhall+.SH SUBCOMMANDS+.PP+\f[B]version\f[R] - Display version information+.PP+\f[B]resolve\f[R] - Resolve imports+.PP+\f[B]type\f[R] - Infer type of expression+.PP+\f[B]normalize\f[R] - Normalize an expression+.PP+\f[B]repl\f[R] - Open a REPL+.PP+\f[B]diff\f[R] - Show difference between two expressions+.PP+\f[B]hash\f[R] - Compute hash of expression+.PP+\f[B]lint\f[R] - Lint an expression, removing dead code+.PP+\f[B]tags\f[R] - Generate etags (Emacs) file+.PP+\f[B]format\f[R] - Format an expression+.PP+\f[B]freeze\f[R] - Add hashes to import statements+.PP+\f[B]encode\f[R] - Encode a Dhall expression (CBOR)+.PP+\f[B]decode\f[R] - Decode a Dhall expression+.PP+\f[B]text\f[R] - Render a Dhall expression to text+.PP+\f[B]to-directory-tree\f[R] - Convert nested record of Text into a+directory+.SH OPTIONS+.TP+\f[B]-h\f[R] \f[B]--help\f[R]+Display help+.TP+\f[B]--file\f[R]+Name of file containing Dhall source+.TP+\f[B]--output\f[R]+Output file+.TP+\f[B]--annotate\f[R]+Add type annotation to output+.TP+\f[B]--alpha\f[R]+alpha-normalize output+.TP+\f[B]--no-cache\f[R]+Don\[cq]t use cache to resolve imports+.TP+\f[B]--explain\f[R]+Explain error messages in detail+.TP+\f[B]--version\f[R]+Display version information+.TP+\f[B]--plain\f[R]+Disable syntax highlighting in output+.TP+\f[B]--ascii\f[R]+Format code using only ASCII syntax+.TP+\f[B]--censor\f[R]+Hide source code from error messages+.SH EDITOR INTEGRATION+.PP+Up-to-date information on editor integration is available at:+.PP+https://docs.dhall-lang.org/howtos/Text-Editor-Configuration.html+.SH BUGS+.PP+Please report any bugs you may come across to+https://github.com/dhall-lang/dhall-haskell/issues.
src/Dhall.hs view
@@ -1,1811 +1,579 @@-{-# LANGUAGE DefaultSignatures          #-}-{-# LANGUAGE DeriveFunctor              #-}-{-# LANGUAGE DeriveGeneric              #-}-{-# LANGUAGE FlexibleInstances          #-}-{-# LANGUAGE FlexibleContexts           #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE MultiWayIf                 #-}-{-# LANGUAGE OverloadedStrings          #-}-{-# LANGUAGE RankNTypes                 #-}-{-# LANGUAGE RecordWildCards            #-}-{-# LANGUAGE ScopedTypeVariables        #-}-{-# LANGUAGE StandaloneDeriving         #-}-{-# LANGUAGE TypeOperators              #-}-{-# LANGUAGE TupleSections              #-}--{-| 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-    , normalizer-    , standardVersion-    , defaultInputSettings-    , InputSettings-    , defaultEvaluateSettings-    , EvaluateSettings-    , HasEvaluateSettings-    , detailed--    -- * Types-    , Type(..)-    , RecordType(..)-    , UnionType(..)-    , InputType(..)-    , Interpret(..)-    , InvalidType(..)-    , auto-    , genericAuto-    , InterpretOptions(..)-    , defaultInterpretOptions-    , bool-    , natural-    , integer-    , scientific-    , double-    , lazyText-    , strictText-    , maybe-    , sequence-    , list-    , vector-    , unit-    , string-    , pair-    , record-    , field-    , union-    , constructor-    , GenericInterpret(..)-    , GenericInject(..)--    , Inject(..)-    , inject-    , genericInject-    , RecordInputType(..)-    , inputFieldWith-    , inputField-    , inputRecord-    , UnionInputType(..)-    , inputConstructorWith-    , inputConstructor-    , inputUnion-    , (>|<)--    -- * 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.Functor.Contravariant (Contravariant(..), (>$<), Op(..))-import Data.Functor.Contravariant.Divisible (Divisible(..), divided)-import Data.Monoid ((<>))-import Data.Scientific (Scientific)-import Data.Sequence (Seq)-import Data.Text (Text)-import Data.Text.Prettyprint.Doc (Pretty)-import Data.Typeable (Typeable)-import Data.Vector (Vector)-import Data.Word (Word8, Word16, Word32, Word64)-import Dhall.Binary (StandardVersion(..))-import Dhall.Core (Expr(..), Chunks(..))-import Dhall.Import (Imported(..))-import Dhall.Parser (Src(..))-import Dhall.TypeCheck (DetailedTypeError(..), TypeError, X)-import GHC.Generics-import Lens.Family (LensLike', set, 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.Semigroup-import qualified Data.Scientific-import qualified Data.Sequence-import qualified Data.Set-import qualified Data.Text-import qualified Data.Text.IO-import qualified Data.Text.Lazy-import qualified Data.Vector-import qualified Dhall.Binary-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.TypeCheck-import qualified Dhall.Util---- $setup--- >>> :set -XOverloadedStrings--- >>> :set -XRecordWildCards--{-| Every `Type` must obey the contract that if an expression's type matches the-    the `expected` type then the `extract` function must succeed.  If not, then-    this exception is thrown--    This exception indicates that an invalid `Type` was provided to the `input`-    function--}-data InvalidType s a = InvalidType-  { invalidTypeExpected :: Expr s a-  , invalidTypeExpression :: Expr s a-  }-  deriving (Typeable)--_ERROR :: String-_ERROR = "\ESC[1;31mError\ESC[0m"--instance (Pretty s, Pretty a, Typeable s, Typeable a) => Show (InvalidType s a) where-    show InvalidType { .. } =-        _ERROR <> ": Invalid Dhall.Type                                                  \n\-        \                                                                                \n\-        \Every Type must provide an extract function that succeeds if an expression      \n\-        \matches the expected type.  You provided a Type that disobeys this contract     \n\-        \                                                                                \n\-        \The Type 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 invalidTypeExpected-          txt1 = Dhall.Util.insert invalidTypeExpression---instance (Pretty s, Pretty a, Typeable s, Typeable a) => Exception (InvalidType s a)---- | @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-  { _startingContext :: Dhall.Context.Context (Expr Src X)-  , _normalizer      :: Maybe (Dhall.Core.ReifiedNormalizer X)-  , _standardVersion :: StandardVersion-  }---- | Default evaluation settings: no extra entries in the initial--- context, and no special normalizer behaviour.------ @since 1.16-defaultEvaluateSettings :: EvaluateSettings-defaultEvaluateSettings = EvaluateSettings-  { _startingContext = Dhall.Context.empty-  , _normalizer      = Nothing-  , _standardVersion = Dhall.Binary.defaultStandardVersion-  }---- | 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 X))-startingContext = evaluateSettings . l-  where-    l :: (Functor f)-      => LensLike' f EvaluateSettings (Dhall.Context.Context (Expr Src X))-    l k s = fmap (\x -> s { _startingContext = x}) (k (_startingContext s))---- | Access the custom normalizer.------ @since 1.16-normalizer-  :: (Functor f, HasEvaluateSettings s)-  => LensLike' f s (Maybe (Dhall.Core.ReifiedNormalizer X))-normalizer = evaluateSettings . l-  where-    l :: (Functor f)-      => LensLike' f EvaluateSettings (Maybe (Dhall.Core.ReifiedNormalizer X))-    l k s = fmap (\x -> s { _normalizer = x }) (k (_normalizer s))---- | Access the standard version (used primarily when encoding or decoding--- Dhall expressions to and from a binary representation)------ @since 1.17-standardVersion-    :: (Functor f, HasEvaluateSettings s)-    => LensLike' f s StandardVersion-standardVersion = evaluateSettings . l-  where-  l k s = fmap (\x -> s { _standardVersion = x}) (k (_standardVersion 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-    :: Type a-    -- ^ The type of value to decode from Dhall to Haskell-    -> 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-    -> Type a-    -- ^ The type of value to decode from Dhall to Haskell-    -> Text-    -- ^ The Dhall program-    -> IO a-    -- ^ The decoded value in Haskell-inputWithSettings settings (Type {..}) txt = do-    expr  <- Dhall.Core.throws (Dhall.Parser.exprFromText (view sourceName settings) txt)--    let InputSettings {..} = settings--    let EvaluateSettings {..} = _evaluateSettings--    let transform =-               set Dhall.Import.standardVersion _standardVersion-            .  set Dhall.Import.normalizer      _normalizer-            .  set Dhall.Import.startingContext _startingContext--    let status = transform (Dhall.Import.emptyStatus _rootDirectory)--    expr' <- State.evalStateT (Dhall.Import.loadWith expr) status--    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-    _ <- Dhall.Core.throws (Dhall.TypeCheck.typeWith (view startingContext settings) annot)-    let normExpr = Dhall.Core.normalizeWith (view normalizer settings) expr'--    case extract normExpr  of-        Just x  -> return x-        Nothing -> Control.Exception.throwIO-                     (InvalidType expected expr')--{-| Type-check and evaluate a Dhall program that is read from the-    file-system.--    This uses the settings from 'defaultEvaluateSettings'.--    @since 1.16--}-inputFile-  :: Type a-  -- ^ The type of value to decode from Dhall to Haskell-  -> 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-  -> Type a-  -- ^ The type of value to decode from Dhall to Haskell-  -> 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 X)-    -- ^ 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 X)-    -- ^ The fully normalized AST-inputExprWithSettings settings txt = do-    expr  <- Dhall.Core.throws (Dhall.Parser.exprFromText (view sourceName settings) txt)--    let InputSettings {..} = settings--    let EvaluateSettings {..} = _evaluateSettings--    let transform =-               set Dhall.Import.standardVersion _standardVersion-            .  set Dhall.Import.normalizer      _normalizer-            .  set Dhall.Import.startingContext _startingContext--    let status = transform (Dhall.Import.emptyStatus _rootDirectory)--    expr' <- State.evalStateT (Dhall.Import.loadWith expr) status--    _ <- Dhall.Core.throws (Dhall.TypeCheck.typeWith (view startingContext settings) expr')-    pure (Dhall.Core.normalizeWith (view normalizer settings) expr')---- | Use this function to extract Haskell values directly from Dhall AST.---   The intended use case is to allow easy extraction of Dhall values for---   making the function `Dhall.Core.normalizeWith` easier to use.------   For other use cases, use `input` from `Dhall` module. It will give you---   a much better user experience.-rawInput-    :: Alternative f-    => Type a-    -- ^ The type of value to decode from Dhall to Haskell-    -> Expr s X-    -- ^ a closed form Dhall program, which evaluates to the expected type-    -> f a-    -- ^ The decoded value in Haskell-rawInput (Type {..}) expr = do-    case extract (Dhall.Core.normalize expr) of-        Just x  -> pure x-        Nothing -> empty--{-| Use this to provide more detailed error messages-->> input auto "True" :: IO Integer-> *** Exception: Error: Expression doesn't match annotation->-> True : Integer->-> (input):1:1-->> detailed (input auto "True") :: IO Integer-> *** Exception: Error: Expression doesn't match annotation->-> Explanation: You can annotate an expression with its type or kind using the-> ❰:❱ symbol, like this:->->->     ┌───────┐->     │ x : t │  ❰x❱ is an expression and ❰t❱ is the annotated type or kind of ❰x❱->     └───────┘->-> The type checker verifies that the expression's type or kind matches the-> provided annotation->-> For example, all of the following are valid annotations that the type checker-> accepts:->->->     ┌─────────────┐->     │ 1 : 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 X) -> IO a-    handler0 (Imported ps e) =-        Control.Exception.throwIO (Imported ps (DetailedTypeError e))--    handler1 :: TypeError Src X -> IO a-    handler1 e = Control.Exception.throwIO (DetailedTypeError e)--{-| A @(Type a)@ represents a way to marshal a value of type @\'a\'@ from Dhall-    into Haskell--    You can produce `Type`s either explicitly:--> example :: Type (Vector Text)-> example = vector text--    ... or implicitly using `auto`:--> example :: Type (Vector Text)-> example = auto--    You can consume `Type`s using the `input` function:--> input :: Type a -> Text -> IO a--}-data Type a = Type-    { extract  :: Expr Src X -> Maybe a-    -- ^ Extracts Haskell value from the Dhall expression-    , expected :: Expr Src X-    -- ^ Dhall type of the Haskell value-    }-    deriving (Functor)--{-| Decode a `Bool`-->>> input bool "True"-True--}-bool :: Type Bool-bool = Type {..}-  where-    extract (BoolLit b) = pure b-    extract  _          = Nothing--    expected = Bool--{-| Decode a `Natural`-->>> input natural "42"-42--}-natural :: Type Natural-natural = Type {..}-  where-    extract (NaturalLit n) = pure n-    extract  _             = empty--    expected = Natural--{-| Decode an `Integer`-->>> input integer "+42"-42--}-integer :: Type Integer-integer = Type {..}-  where-    extract (IntegerLit n) = pure n-    extract  _             = empty--    expected = Integer--{-| Decode a `Scientific`-->>> input scientific "1e100"-1.0e100--}-scientific :: Type Scientific-scientific = fmap Data.Scientific.fromFloatDigits double--{-| Decode a `Double`-->>> input double "42.0"-42.0--}-double :: Type Double-double = Type {..}-  where-    extract (DoubleLit n) = pure n-    extract  _            = empty--    expected = Double--{-| Decode lazy `Text`-->>> input lazyText "\"Test\""-"Test"--}-lazyText :: Type Data.Text.Lazy.Text-lazyText = Type {..}-  where-    extract (TextLit (Chunks [] t)) = pure (Data.Text.Lazy.fromStrict t)-    extract  _                      = empty--    expected = Text--{-| Decode strict `Text`-->>> input strictText "\"Test\""-"Test"--}-strictText :: Type Text-strictText = fmap Data.Text.Lazy.toStrict lazyText--{-| Decode a `Maybe`-->>> input (maybe natural) "Some 1"-Just 1--}-maybe :: Type a -> Type (Maybe a)-maybe (Type extractIn expectedIn) = Type extractOut expectedOut-  where-    extractOut (Some e    ) = fmap Just (extractIn e)-    extractOut (App None _) = return Nothing-    extractOut _            = empty--    expectedOut = App Optional expectedIn--{-| Decode a `Seq`-->>> input (sequence natural) "[1, 2, 3]"-fromList [1,2,3]--}-sequence :: Type a -> Type (Seq a)-sequence (Type extractIn expectedIn) = Type extractOut expectedOut-  where-    extractOut (ListLit _ es) = traverse extractIn es-    extractOut  _             = Nothing--    expectedOut = App List expectedIn--{-| Decode a list-->>> input (list natural) "[1, 2, 3]"-[1,2,3]--}-list :: Type a -> Type [a]-list = fmap Data.Foldable.toList . sequence--{-| Decode a `Vector`-->>> input (vector natural) "[1, 2, 3]"-[1,2,3]--}-vector :: Type a -> Type (Vector a)-vector = fmap Data.Vector.fromList . list--{-| Decode @()@ from an empty record.-->>> input unit "{=}"  -- GHC doesn't print the result if it is ()---}-unit :: Type ()-unit = Type extractOut expectedOut-  where-    extractOut (RecordLit fields)-        | Data.Foldable.null fields = return ()-    extractOut _ = Nothing--    expectedOut = Record mempty--{-| Decode a `String`-->>> input string "\"ABC\""-"ABC"---}-string :: Type String-string = Data.Text.Lazy.unpack <$> lazyText--{-| Given a pair of `Type`s, decode a tuple-record into their pairing.-->>> input (pair natural bool) "{ _1 = 42, _2 = False }"-(42,False)--}-pair :: Type a -> Type b -> Type (a, b)-pair l r = Type extractOut expectedOut-  where-    extractOut (RecordLit fields) =-      (,) <$> ( Dhall.Map.lookup "_1" fields >>= extract l )-          <*> ( Dhall.Map.lookup "_2" fields >>= extract r )-    extractOut _ = Nothing--    expectedOut =-        Record-            (Dhall.Map.fromList-                [ ("_1", expected l)-                , ("_2", expected r)-                ]-            )--{-| Any value that implements `Interpret` can be automatically decoded based on-    the inferred return type of `input`-->>> input auto "[1, 2, 3]" :: IO (Vector Natural)-[1,2,3]--    This class auto-generates a default implementation for records that-    implement `Generic`.  This does not auto-generate an instance for recursive-    types.--}-class Interpret a where-    autoWith:: InterpretOptions -> Type a-    default autoWith-        :: (Generic a, GenericInterpret (Rep a)) => InterpretOptions -> Type a-    autoWith options = fmap GHC.Generics.to (evalState (genericAutoWith options) 1)--instance Interpret Bool where-    autoWith _ = bool--instance Interpret Natural where-    autoWith _ = natural--instance Interpret Integer where-    autoWith _ = integer--instance Interpret Scientific where-    autoWith _ = scientific--instance Interpret Double where-    autoWith _ = double--instance {-# OVERLAPS #-} Interpret [Char] where-    autoWith _ = string--instance Interpret Data.Text.Lazy.Text where-    autoWith _ = lazyText--instance Interpret Text where-    autoWith _ = strictText--instance Interpret a => Interpret (Maybe a) where-    autoWith opts = maybe (autoWith opts)--instance Interpret a => Interpret (Seq a) where-    autoWith opts = sequence (autoWith opts)--instance Interpret a => Interpret [a] where-    autoWith = fmap (fmap Data.Vector.toList) autoWith--instance Interpret a => Interpret (Vector a) where-    autoWith opts = vector (autoWith opts)--instance (Inject a, Interpret b) => Interpret (a -> b) where-    autoWith opts = Type extractOut expectedOut-      where-        normalizer_ = Just (inputNormalizer opts)--        extractOut e = Just (\i -> case extractIn (Dhall.Core.normalizeWith normalizer_ (App e (embed i))) of-            Just o  -> o-            Nothing -> error "Interpret: You cannot decode a function if it does not have the correct type" )--        expectedOut = Pi "_" declared expectedIn--        InputType {..} = inject--        Type extractIn expectedIn = autoWith opts--instance (Interpret a, Interpret b) => Interpret (a, b)--{-| Use the default options for interpreting a configuration file--> auto = autoWith defaultInterpretOptions--}-auto :: Interpret a => Type a-auto = autoWith defaultInterpretOptions--{-| `genericAuto` is the default implementation for `auto` if you derive-    `Interpret`.  The difference is that you can use `genericAuto` without-    having to explicitly provide an `Interpret` instance for a type as long as-    the type derives `Generic`--}-genericAuto :: (Generic a, GenericInterpret (Rep a)) => Type a-genericAuto = fmap to (evalState (genericAutoWith defaultInterpretOptions) 1)--{-| Use these options to tweak how Dhall derives a generic implementation of-    `Interpret`--}-data InterpretOptions = InterpretOptions-    { fieldModifier       :: Text -> Text-    -- ^ Function used to transform Haskell field names into their corresponding-    --   Dhall field names-    , constructorModifier :: Text -> Text-    -- ^ Function used to transform Haskell constructor names into their-    --   corresponding Dhall alternative names-    , inputNormalizer     :: Dhall.Core.ReifiedNormalizer X-    -- ^ This is only used by the `Interpret` instance for functions in order-    --   to normalize the function input before marshaling the input into a-    --   Dhall expression-    }--{-| Default interpret options, which you can tweak or override, like this:--> autoWith->     (defaultInterpretOptions { fieldModifier = Data.Text.Lazy.dropWhile (== '_') })--}-defaultInterpretOptions :: InterpretOptions-defaultInterpretOptions = InterpretOptions-    { fieldModifier       = id-    , constructorModifier = id-    , inputNormalizer     = Dhall.Core.ReifiedNormalizer (const (pure Nothing))-    }--{-| This is the underlying class that powers the `Interpret` class's support-    for automatically deriving a generic implementation--}-class GenericInterpret f where-    genericAutoWith :: InterpretOptions -> State Int (Type (f a))--instance GenericInterpret f => GenericInterpret (M1 D d f) where-    genericAutoWith options = do-        res <- genericAutoWith options-        pure (fmap M1 res)--instance GenericInterpret V1 where-    genericAutoWith _ = pure Type {..}-      where-        extract _ = Nothing--        expected = Union mempty--unsafeExpectUnion-    :: Text -> Expr Src X -> Dhall.Map.Map Text (Maybe (Expr Src X))-unsafeExpectUnion _ (Union kts) =-    kts-unsafeExpectUnion name expression =-    Dhall.Core.internalError-        (name <> ": Unexpected constructor: " <> Dhall.Core.pretty expression)--unsafeExpectRecord :: Text -> Expr Src X -> Dhall.Map.Map Text (Expr Src X)-unsafeExpectRecord _ (Record kts) =-    kts-unsafeExpectRecord name expression =-    Dhall.Core.internalError-        (name <> ": Unexpected constructor: " <> Dhall.Core.pretty expression)--unsafeExpectUnionLit-    :: Text-    -> Expr Src X-    -> (Text, Maybe (Expr Src X))-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 X -> Dhall.Map.Map Text (Expr Src X)-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 (UnionLit fld e rest) =-  return (fld, e, rest)-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--instance (Constructor c1, Constructor c2, GenericInterpret f1, GenericInterpret f2) => GenericInterpret (M1 C c1 f1 :+: M1 C c2 f2) where-    genericAutoWith options@(InterpretOptions {..}) = pure (Type {..})-      where-        nL :: M1 i c1 f1 a-        nL = undefined--        nR :: M1 i c2 f2 a-        nR = undefined--        nameL = constructorModifier (Data.Text.pack (conName nL))-        nameR = constructorModifier (Data.Text.pack (conName nR))--        extract e0 = do-          (name, e1, _) <- extractUnionConstructor e0-          if-            | name == nameL -> fmap (L1 . M1) (extractL e1)-            | name == nameR -> fmap (R1 . M1) (extractR e1)-            | otherwise     -> Nothing--        expected =-            Union-                (Dhall.Map.fromList-                    [ (nameL, notEmptyRecord expectedL)-                    , (nameR, notEmptyRecord expectedR)-                    ]-                )--        Type extractL expectedL = evalState (genericAutoWith options) 1-        Type extractR expectedR = evalState (genericAutoWith options) 1--instance (Constructor c, GenericInterpret (f :+: g), GenericInterpret h) => GenericInterpret ((f :+: g) :+: M1 C c h) where-    genericAutoWith options@(InterpretOptions {..}) = pure (Type {..})-      where-        n :: M1 i c h a-        n = undefined--        name = constructorModifier (Data.Text.pack (conName n))--        extract u = do-          (name', e, _) <- extractUnionConstructor u-          if-            | name == name' -> fmap (R1 . M1) (extractR e)-            | otherwise     -> fmap  L1       (extractL u)--        expected =-            Union (Dhall.Map.insert name (notEmptyRecord expectedR) ktsL)--        Type extractL expectedL = evalState (genericAutoWith options) 1-        Type extractR expectedR = evalState (genericAutoWith options) 1--        ktsL = unsafeExpectUnion "genericAutoWith (:+:)" expectedL--instance (Constructor c, GenericInterpret f, GenericInterpret (g :+: h)) => GenericInterpret (M1 C c f :+: (g :+: h)) where-    genericAutoWith options@(InterpretOptions {..}) = pure (Type {..})-      where-        n :: M1 i c f a-        n = undefined--        name = constructorModifier (Data.Text.pack (conName n))--        extract u = do-          (name', e, _) <- extractUnionConstructor u-          if-            | name == name' -> fmap (L1 . M1) (extractL e)-            | otherwise     -> fmap  R1       (extractR u)--        expected =-            Union (Dhall.Map.insert name (notEmptyRecord expectedL) ktsR)--        Type extractL expectedL = evalState (genericAutoWith options) 1-        Type extractR expectedR = evalState (genericAutoWith options) 1--        ktsR = unsafeExpectUnion "genericAutoWith (:+:)" expectedR--instance (GenericInterpret (f :+: g), GenericInterpret (h :+: i)) => GenericInterpret ((f :+: g) :+: (h :+: i)) where-    genericAutoWith options = pure (Type {..})-      where-        extract e = fmap L1 (extractL e) <|> fmap R1 (extractR e)--        expected = Union (Dhall.Map.union ktsL ktsR)--        Type extractL expectedL = evalState (genericAutoWith options) 1-        Type extractR expectedR = evalState (genericAutoWith options) 1--        ktsL = unsafeExpectUnion "genericAutoWith (:+:)" expectedL-        ktsR = unsafeExpectUnion "genericAutoWith (:+:)" expectedR--instance GenericInterpret f => GenericInterpret (M1 C c f) where-    genericAutoWith options = do-        res <- genericAutoWith options-        pure (fmap M1 res)--instance GenericInterpret U1 where-    genericAutoWith _ = pure (Type {..})-      where-        extract _ = Just U1--        expected = Record (Dhall.Map.fromList [])--instance (GenericInterpret f, GenericInterpret g) => GenericInterpret (f :*: g) where-    genericAutoWith options = do-        Type extractL expectedL <- genericAutoWith options-        Type extractR expectedR <- genericAutoWith options-        let ktsL = unsafeExpectRecord "genericAutoWith (:*:)"expectedL-        let ktsR = unsafeExpectRecord "genericAutoWith (:*:)"expectedR-        pure-            (Type-                { extract = liftA2 (liftA2 (:*:)) extractL extractR-                , expected = Record (Dhall.Map.union ktsL ktsR)-                }-            )--getSelName :: Selector s => M1 i s f a -> State Int String-getSelName n = case selName n of-    "" -> do i <- get-             put (i + 1)-             pure ("_" ++ show i)-    nn -> pure nn--instance (Selector s, Interpret a) => GenericInterpret (M1 S s (K1 i a)) where-    genericAutoWith opts@(InterpretOptions {..}) = do-        name <- getSelName n-        let extract (RecordLit m) = do-                    let name' = fieldModifier (Data.Text.pack name)-                    e <- Dhall.Map.lookup name' m-                    fmap (M1 . K1) (extract' e)-            extract _            = Nothing-        let expected =-                Record (Dhall.Map.fromList [(key, expected')])-              where-                key = fieldModifier (Data.Text.pack name)-        pure (Type {..})-      where-        n :: M1 i s f a-        n = undefined--        Type extract' expected' = autoWith opts--{-| An @(InputType a)@ represents a way to marshal a value of type @\'a\'@ from-    Haskell into Dhall--}-data InputType a = InputType-    { embed    :: a -> Expr Src X-    -- ^ Embeds a Haskell value as a Dhall expression-    , declared :: Expr Src X-    -- ^ Dhall type of the Haskell value-    }--instance Contravariant InputType where-    contramap f (InputType embed declared) = InputType embed' declared-      where-        embed' x = embed (f x)--{-| This class is used by `Interpret` instance for functions:--> instance (Inject a, Interpret b) => Interpret (a -> b)--    You can convert Dhall functions with "simple" inputs (i.e. instances of this-    class) into Haskell functions.  This works by:--    * Marshaling the input to the Haskell function into a Dhall expression (i.e.-      @x :: Expr Src X@)-    * Applying the Dhall function (i.e. @f :: Expr Src X@) to the Dhall input-      (i.e. @App f x@)-    * Normalizing the syntax tree (i.e. @normalize (App f x)@)-    * Marshaling the resulting Dhall expression back into a Haskell value--}-class Inject a where-    injectWith :: InterpretOptions -> InputType a-    default injectWith-        :: (Generic a, GenericInject (Rep a)) => InterpretOptions -> InputType a-    injectWith options-        = contramap GHC.Generics.from (evalState (genericInjectWith options) 1)--{-| Use the default options for injecting a value--> inject = inject defaultInterpretOptions--}-inject :: Inject a => InputType a-inject = injectWith defaultInterpretOptions--{-| Use the default options for injecting a value, whose structure is-determined generically.--This can be used when you want to use 'Inject' on types that you don't-want to define orphan instances for.--}-genericInject-  :: (Generic a, GenericInject (Rep a)) => InputType a-genericInject-    = contramap GHC.Generics.from (evalState (genericInjectWith defaultInterpretOptions) 1)--instance Inject Bool where-    injectWith _ = InputType {..}-      where-        embed = BoolLit--        declared = Bool--instance Inject Data.Text.Lazy.Text where-    injectWith _ = InputType {..}-      where-        embed text =-            TextLit (Chunks [] (Data.Text.Lazy.toStrict text))--        declared = Text--instance Inject Text where-    injectWith _ = InputType {..}-      where-        embed text = TextLit (Chunks [] text)--        declared = Text--instance Inject Natural where-    injectWith _ = InputType {..}-      where-        embed = NaturalLit--        declared = Natural--instance Inject Integer where-    injectWith _ = InputType {..}-      where-        embed = IntegerLit--        declared = Integer--instance Inject Int where-    injectWith _ = InputType {..}-      where-        embed = IntegerLit . toInteger--        declared = Integer--instance Inject Word8 where-    injectWith _ = InputType {..}-      where-        embed = IntegerLit . toInteger--        declared = Integer--instance Inject Word16 where-    injectWith _ = InputType {..}-      where-        embed = IntegerLit . toInteger--        declared = Integer--instance Inject Word32 where-    injectWith _ = InputType {..}-      where-        embed = IntegerLit . toInteger--        declared = Integer--instance Inject Word64 where-    injectWith _ = InputType {..}-      where-        embed = IntegerLit . toInteger--        declared = Integer--instance Inject Double where-    injectWith _ = InputType {..}-      where-        embed = DoubleLit--        declared = Double--instance Inject () where-    injectWith _ = InputType {..}-      where-        embed = const (RecordLit mempty)--        declared = Record mempty--instance Inject a => Inject (Maybe a) where-    injectWith options = InputType embedOut declaredOut-      where-        embedOut (Just x) =-            OptionalLit declaredIn (pure (embedIn x))-        embedOut Nothing =-            OptionalLit declaredIn  empty--        InputType embedIn declaredIn = injectWith options--        declaredOut = App Optional declaredIn--instance Inject a => Inject (Seq a) where-    injectWith options = InputType embedOut declaredOut-      where-        embedOut xs = ListLit (Just declaredIn) (fmap embedIn xs)--        declaredOut = App List declaredIn--        InputType embedIn declaredIn = injectWith options--instance Inject a => Inject [a] where-    injectWith = fmap (contramap Data.Sequence.fromList) injectWith--instance Inject a => Inject (Vector a) where-    injectWith = fmap (contramap Data.Vector.toList) injectWith--instance Inject a => Inject (Data.Set.Set a) where-    injectWith = fmap (contramap Data.Set.toList) injectWith--instance (Inject a, Inject b) => Inject (a, b)--{-| This is the underlying class that powers the `Interpret` class's support-    for automatically deriving a generic implementation--}-class GenericInject f where-    genericInjectWith :: InterpretOptions -> State Int (InputType (f a))--instance GenericInject f => GenericInject (M1 D d f) where-    genericInjectWith options = do-        res <- genericInjectWith options-        pure (contramap unM1 res)--instance GenericInject f => GenericInject (M1 C c f) where-    genericInjectWith options = do-        res <- genericInjectWith options-        pure (contramap unM1 res)--instance (Constructor c1, Constructor c2, GenericInject f1, GenericInject f2) => GenericInject (M1 C c1 f1 :+: M1 C c2 f2) where-    genericInjectWith options@(InterpretOptions {..}) = pure (InputType {..})-      where-        embed (L1 (M1 l)) =-            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))--        InputType embedL declaredL = evalState (genericInjectWith options) 1-        InputType embedR declaredR = evalState (genericInjectWith options) 1--instance (Constructor c, GenericInject (f :+: g), GenericInject h) => GenericInject ((f :+: g) :+: M1 C c h) where-    genericInjectWith options@(InterpretOptions {..}) = pure (InputType {..})-      where-        embed (L1 l) =-            case maybeValL of-                Nothing   -> Field declared keyL-                Just valL -> App (Field declared keyL) valL-          where-            (keyL, maybeValL) =-              unsafeExpectUnionLit "genericInjectWith (:+:)" (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)--        InputType embedL declaredL = evalState (genericInjectWith options) 1-        InputType embedR declaredR = evalState (genericInjectWith options) 1--        ktsL = unsafeExpectUnion "genericInjectWith (:+:)" declaredL--instance (Constructor c, GenericInject f, GenericInject (g :+: h)) => GenericInject (M1 C c f :+: (g :+: h)) where-    genericInjectWith options@(InterpretOptions {..}) = pure (InputType {..})-      where-        embed (L1 (M1 l)) =-            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 "genericInjectWith (:+:)" (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)--        InputType embedL declaredL = evalState (genericInjectWith options) 1-        InputType embedR declaredR = evalState (genericInjectWith options) 1--        ktsR = unsafeExpectUnion "genericInjectWith (:+:)" declaredR--instance (GenericInject (f :+: g), GenericInject (h :+: i)) => GenericInject ((f :+: g) :+: (h :+: i)) where-    genericInjectWith options = pure (InputType {..})-      where-        embed (L1 l) =-            case maybeValL of-                Nothing   -> Field declared keyL-                Just valL -> App (Field declared keyL) valL-          where-            (keyL, maybeValL) =-                unsafeExpectUnionLit "genericInjectWith (:+:)" (embedL l)-        embed (R1 r) =-            case maybeValR of-                Nothing   -> Field declared keyR-                Just valR -> App (Field declared keyR) valR-          where-            (keyR, maybeValR) =-                unsafeExpectUnionLit "genericInjectWith (:+:)" (embedR r)--        declared = Union (Dhall.Map.union ktsL ktsR)--        InputType embedL declaredL = evalState (genericInjectWith options) 1-        InputType embedR declaredR = evalState (genericInjectWith options) 1--        ktsL = unsafeExpectUnion "genericInjectWith (:+:)" declaredL-        ktsR = unsafeExpectUnion "genericInjectWith (:+:)" declaredR--instance (GenericInject f, GenericInject g) => GenericInject (f :*: g) where-    genericInjectWith options = do-        InputType embedInL declaredInL <- genericInjectWith options-        InputType embedInR declaredInR <- genericInjectWith options--        let embed (l :*: r) =-                RecordLit (Dhall.Map.union mapL mapR)-              where-                mapL =-                    unsafeExpectRecordLit "genericInjectWith (:*:)" (embedInL l)--                mapR =-                    unsafeExpectRecordLit "genericInjectWith (:*:)" (embedInR r)--        let declared = Record (Dhall.Map.union mapL mapR)-              where-                mapL = unsafeExpectRecord "genericInjectWith (:*:)" declaredInL-                mapR = unsafeExpectRecord "genericInjectWith (:*:)" declaredInR--        pure (InputType {..})--instance GenericInject U1 where-    genericInjectWith _ = pure (InputType {..})-      where-        embed _ = RecordLit mempty--        declared = Record mempty--instance (Selector s, Inject a) => GenericInject (M1 S s (K1 i a)) where-    genericInjectWith opts@(InterpretOptions {..}) = do-        name <- fieldModifier . Data.Text.pack <$> getSelName n-        let embed (M1 (K1 x)) =-                RecordLit (Dhall.Map.singleton name (embedIn x))-        let declared =-                Record (Dhall.Map.singleton name declaredIn)-        pure (InputType {..})-      where-        n :: M1 i s f a-        n = undefined--        InputType embedIn declaredIn = injectWith opts--{-| The 'RecordType' applicative functor allows you to build a 'Type' parser-    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 parser has type 'Type' @Project@, but we can't build that out of any-    smaller parsers, as 'Type's cannot be combined (they are only 'Functor's).-    However, we can use a 'RecordType' to build a 'Type' for @Project@:-->>> :{-project :: Type Project-project =-  record-    ( Project <$> field "name" strictText-              <*> field "description" strictText-              <*> field "stars" natural-    )-:}--}--newtype RecordType a =-  RecordType-    ( Data.Functor.Product.Product-        ( Control.Applicative.Const-            ( Dhall.Map.Map-                Text-                ( Expr Src X )-            )-        )-        ( Data.Functor.Compose.Compose-            ( (->) ( Expr Src X ) )-            Maybe-        )-        a-    )-  deriving (Functor, Applicative)----- | Run a 'RecordType' parser to build a 'Type' parser.-record :: RecordType a -> Dhall.Type a-record ( RecordType ( Data.Functor.Product.Pair ( Control.Applicative.Const fields ) ( Data.Functor.Compose.Compose extractF ) ) ) =-  Type-    { extract =-        extractF-    , expected =-        Record fields-    }----- | Parse a single field of a record.-field :: Text -> Type a -> RecordType a-field key valueType =-  let-    extractBody expr = do-      RecordLit fields <--        return expr--      Dhall.Map.lookup key fields-        >>= extract valueType--  in-    RecordType-      ( Data.Functor.Product.Pair-          ( Control.Applicative.Const-              ( Dhall.Map.singleton-                  key-                  ( Dhall.expected valueType )-              )-          )-          ( Data.Functor.Compose.Compose extractBody )-      )--{-| The 'UnionType' monoid allows you to build a 'Type' parser-    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 = "Finish succesfully"-> | Queued : Natural-> | Errored : Text-> >--    Our parser has type 'Type' @Status@, but we can't build that out of any-    smaller parsers, as 'Type's cannot be combined (they are only 'Functor's).-    However, we can use a 'UnionType' to build a 'Type' for @Status@:-->>> :{-status :: Type Status-status = union-  (  ( Queued  <$> constructor "Queued"  natural )-  <> ( Result  <$> constructor "Result"  strictText )-  <> ( Errored <$> constructor "Errored" strictText )-  )-:}---}-newtype UnionType a =-    UnionType-      ( Data.Functor.Compose.Compose (Dhall.Map.Map Text) Type a )-  deriving (Functor)--instance Data.Semigroup.Semigroup (UnionType a) where-    (<>) = coerce ((<>) :: Dhall.Map.Map Text (Type a) -> Dhall.Map.Map Text (Type a) -> Dhall.Map.Map Text (Type a))--instance Monoid (UnionType a) where-    mempty = coerce (mempty :: Dhall.Map.Map Text (Type a))-    mappend = (Data.Semigroup.<>)---- | Run a 'UnionType' parser to build a 'Type' parser.-union :: UnionType a -> Type a-union (UnionType (Data.Functor.Compose.Compose mp)) = Type-    { extract  = extractF-    , expected = Union expect-    }-  where-    expect = (notEmptyRecord . Dhall.expected) <$> mp--    extractF e0 = 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)--      extract t e1---- | Parse a single constructor of a union-constructor :: Text -> Type a -> UnionType a-constructor key valueType = UnionType-    ( Data.Functor.Compose.Compose (Dhall.Map.singleton key valueType) )--{-| The 'RecordInputType' divisible (contravariant) functor allows you to build-    an 'InputType' injector 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 injector has type 'InputType' @Project@, but we can't build that out of any-    smaller injectors, as 'InputType's cannot be combined (they are only 'Contravariant's).-    However, we can use an 'InputRecordType' to build an 'InputType' for @Project@:-->>> :{-injectProject :: InputType Project-injectProject =-  inputRecord-    ( adapt >$< inputFieldWith "name" inject-            >*< inputFieldWith "description" inject-            >*< inputFieldWith "stars" inject-    )-  where-    adapt (Project{..}) = (projectName, (projectDescription, projectStars))-:}--    Or, since we are simply using the `Inject` instance to inject each field, we could write-->>> :{-injectProject :: InputType Project-injectProject =-  inputRecord-    ( adapt >$< inputField "name"-            >*< inputField "description"-            >*< inputField "stars"-    )-  where-    adapt (Project{..}) = (projectName, (projectDescription, projectStars))-:}---}---- | Infix 'divided'-(>*<) :: Divisible f => f a -> f b -> f (a, b)-(>*<) = divided--infixr 5 >*<--newtype RecordInputType a-  = RecordInputType (Dhall.Map.Map Text (InputType a))--instance Contravariant RecordInputType where-  contramap f (RecordInputType inputTypeRecord) = RecordInputType $ contramap f <$> inputTypeRecord--instance Divisible RecordInputType where-  divide f (RecordInputType bInputTypeRecord) (RecordInputType cInputTypeRecord) =-      RecordInputType-    $ Dhall.Map.union-      ((contramap $ fst . f) <$> bInputTypeRecord)-      ((contramap $ snd . f) <$> cInputTypeRecord)-  conquer = RecordInputType mempty--inputFieldWith :: Text -> InputType a -> RecordInputType a-inputFieldWith name inputType = RecordInputType $ Dhall.Map.singleton name inputType--inputField :: Inject a => Text -> RecordInputType a-inputField name = inputFieldWith name inject--inputRecord :: RecordInputType a -> InputType a-inputRecord (RecordInputType inputTypeRecord) = InputType makeRecordLit recordType-  where-    recordType = Record $ declared <$> inputTypeRecord-    makeRecordLit x = RecordLit $ (($ x) . embed) <$> inputTypeRecord--{-| The 'UnionInputType' monoid allows you to build-    an 'InputType' injector 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 = "Finish succesfully"-> | Queued : Natural-> | Errored : Text-> >--    Our injector has type 'InputType' @Status@, but we can't build that out of any-    smaller injectors, as 'InputType's cannot be combined.-    However, we can use an 'UnionInputType' to build an 'InputType' for @Status@:-->>> :{-injectStatus :: InputType Status-injectStatus = adapt >$< inputUnion-  (   inputConstructorWith "Queued"  inject-  >|< inputConstructorWith "Result"  inject-  >|< inputConstructorWith "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 `Inject` instance to inject each branch, we could write-->>> :{-injectStatus :: InputType Status-injectStatus = adapt >$< inputUnion-  (   inputConstructor "Queued"-  >|< inputConstructor "Result"-  >|< inputConstructor "Errored"-  )-  where-    adapt (Queued  n) = Left n-    adapt (Result  t) = Right (Left t)-    adapt (Errored e) = Right (Right e)-:}---}-newtype UnionInputType a =-  UnionInputType-    ( Data.Functor.Product.Product-        ( Control.Applicative.Const-            ( Dhall.Map.Map-                Text-                ( Expr Src X )-            )-        )-        ( Op (Text, Expr Src X) )-        a-    )-  deriving (Contravariant)---- | Combines two 'UnionInputType' values.  See 'UnionInputType' for usage--- notes.------ Ideally, this matches 'Data.Functor.Contravariant.Divisible.chosen';--- however, this allows 'UnionInputType' to not need a 'Divisible' instance--- itself (since no instance is possible).-(>|<) :: UnionInputType a -> UnionInputType b -> UnionInputType (Either a b)-UnionInputType (Data.Functor.Product.Pair (Control.Applicative.Const mx) (Op fx))-    >|< UnionInputType (Data.Functor.Product.Pair (Control.Applicative.Const my) (Op fy)) =-    UnionInputType-      ( Data.Functor.Product.Pair-          ( Control.Applicative.Const (mx <> my) )-          ( Op (either fx fy) )-      )--infixr 5 >|<--inputUnion :: UnionInputType a -> InputType a-inputUnion ( UnionInputType ( Data.Functor.Product.Pair ( Control.Applicative.Const fields ) ( Op embedF ) ) ) =-    InputType-      { 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--inputConstructorWith-    :: Text-    -> InputType a-    -> UnionInputType a-inputConstructorWith name inputType = UnionInputType $-    Data.Functor.Product.Pair-      ( Control.Applicative.Const-          ( Dhall.Map.singleton-              name-              ( declared inputType )-          )-      )-      ( Op ( (name,) . embed inputType )-      )--inputConstructor-    :: Inject a-    => Text-    -> UnionInputType a-inputConstructor name = inputConstructorWith 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,958 +1,1437 @@-{-# LANGUAGE RecordWildCards    #-}-{-# LANGUAGE OverloadedStrings  #-}--{-| This module contains logic for converting Dhall expressions to and from-    CBOR expressions which can in turn be converted to and from a binary-    representation--}--module Dhall.Binary-    ( -- * Standard versions-      StandardVersion(..)-    , defaultStandardVersion-    , parseStandardVersion-    , renderStandardVersion--    -- * Encoding and decoding-    , ToTerm(..)-    , FromTerm(..)-    , encodeExpression-    , decodeExpression--    -- * Exceptions-    , DecodingFailure(..)-    ) where--import Codec.CBOR.Term (Term(..))-import Control.Applicative (empty, (<|>))-import Control.Exception (Exception)-import Dhall.Core-    ( Binding(..)-    , Chunks(..)-    , Const(..)-    , Directory(..)-    , Expr(..)-    , File(..)-    , FilePrefix(..)-    , Import(..)-    , ImportHashed(..)-    , ImportMode(..)-    , ImportType(..)-    , Scheme(..)-    , URL(..)-    , Var(..)-    )--import Data.Foldable (toList)-import Data.List.NonEmpty (NonEmpty(..))-import Data.Monoid ((<>))-import Data.Text (Text)-import Options.Applicative (Parser)-import Prelude hiding (exponent)-import GHC.Float (double2Float, float2Double)--import qualified Crypto.Hash-import qualified Data.ByteArray-import qualified Data.ByteString-import qualified Data.Sequence-import qualified Dhall.Map-import qualified Dhall.Set-import qualified Options.Applicative---- | Supported version strings-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)--defaultStandardVersion :: StandardVersion-defaultStandardVersion = NoVersion--parseStandardVersion :: Parser StandardVersion-parseStandardVersion =-    Options.Applicative.option readVersion-        (   Options.Applicative.long "standard-version"-        <>  Options.Applicative.metavar "X.Y.Z"-        <>  Options.Applicative.help "The standard version to use"-        <>  Options.Applicative.value defaultStandardVersion-        )-  where-    readVersion = do-        string <- Options.Applicative.str-        case string :: Text of-            "none"  -> return NoVersion-            "1.0.0" -> return V_1_0_0-            "2.0.0" -> return V_2_0_0-            "3.0.0" -> return V_3_0_0-            "4.0.0" -> return V_4_0_0-            "5.0.0" -> return V_5_0_0-            _       -> fail "Unsupported version"--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"--{-| Convert a function applied to multiple arguments to the base function and-    the list of arguments--}-unApply :: Expr s a -> (Expr s a, [Expr s a])-unApply e₀ = (baseFunction₀, diffArguments₀ [])-  where-    ~(baseFunction₀, diffArguments₀) = go e₀--    go (App f a) = (baseFunction, diffArguments . (a :))-      where-        ~(baseFunction, diffArguments) = go f--    go (Note _ e) = go e--    go baseFunction = (baseFunction, id)---- | Types that can be encoded as a CBOR `Term`-class ToTerm a where-    encode :: a -> Term--instance ToTerm a => ToTerm (Expr s a) where-    encode (Var (V "_" n)) =-        TInteger n-    encode (Var (V x n)) =-        TList [ TString x, TInteger n ]-    encode NaturalBuild =-        TString "Natural/build"-    encode NaturalFold =-        TString "Natural/fold"-    encode NaturalIsZero =-        TString "Natural/isZero"-    encode NaturalEven =-        TString "Natural/even"-    encode NaturalOdd =-        TString "Natural/odd"-    encode NaturalToInteger =-        TString "Natural/toInteger"-    encode NaturalShow =-        TString "Natural/show"-    encode IntegerToDouble =-        TString "Integer/toDouble"-    encode IntegerShow =-        TString "Integer/show"-    encode DoubleShow =-        TString "Double/show"-    encode ListBuild =-        TString "List/build"-    encode ListFold =-        TString "List/fold"-    encode ListLength =-        TString "List/length"-    encode ListHead =-        TString "List/head"-    encode ListLast =-        TString "List/last"-    encode ListIndexed =-        TString "List/indexed"-    encode ListReverse =-        TString "List/reverse"-    encode OptionalFold =-        TString "Optional/fold"-    encode OptionalBuild =-        TString "Optional/build"-    encode Bool =-        TString "Bool"-    encode Optional =-        TString "Optional"-    encode None =-        TString "None"-    encode Natural =-        TString "Natural"-    encode Integer =-        TString "Integer"-    encode Double =-        TString "Double"-    encode Text =-        TString "Text"-    encode TextShow =-        TString "Text/show"-    encode List =-        TString "List"-    encode (Const Type) =-        TString "Type"-    encode (Const Kind) =-        TString "Kind"-    encode (Const Sort) =-        TString "Sort"-    encode e@(App _ _) =-        TList ([ TInt 0, f₁ ] ++ map encode arguments)-      where-        (f₀, arguments) = unApply e--        f₁ = encode f₀-    encode (Lam "_" _A₀ b₀) =-        TList [ TInt 1, _A₁, b₁ ]-      where-        _A₁ = encode _A₀-        b₁  = encode b₀-    encode (Lam x _A₀ b₀) =-        TList [ TInt 1, TString x, _A₁, b₁ ]-      where-        _A₁ = encode _A₀-        b₁  = encode b₀-    encode (Pi "_" _A₀ _B₀) =-        TList [ TInt 2, _A₁, _B₁ ]-      where-        _A₁ = encode _A₀-        _B₁ = encode _B₀-    encode (Pi x _A₀ _B₀) =-        TList [ TInt 2, TString x, _A₁, _B₁ ]-      where-        _A₁ = encode _A₀-        _B₁ = encode _B₀-    encode (BoolOr l₀ r₀) =-        TList [ TInt 3, TInt 0, l₁, r₁ ]-      where-        l₁ = encode l₀-        r₁ = encode r₀-    encode (BoolAnd l₀ r₀) =-        TList [ TInt 3, TInt 1, l₁, r₁ ]-      where-        l₁ = encode l₀-        r₁ = encode r₀-    encode (BoolEQ l₀ r₀) =-        TList [ TInt 3, TInt 2, l₁, r₁ ]-      where-        l₁ = encode l₀-        r₁ = encode r₀-    encode (BoolNE l₀ r₀) =-        TList [ TInt 3, TInt 3, l₁, r₁ ]-      where-        l₁ = encode l₀-        r₁ = encode r₀-    encode (NaturalPlus l₀ r₀) =-        TList [ TInt 3, TInt 4, l₁, r₁ ]-      where-        l₁ = encode l₀-        r₁ = encode r₀-    encode (NaturalTimes l₀ r₀) =-        TList [ TInt 3, TInt 5, l₁, r₁ ]-      where-        l₁ = encode l₀-        r₁ = encode r₀-    encode (TextAppend l₀ r₀) =-        TList [ TInt 3, TInt 6, l₁, r₁ ]-      where-        l₁ = encode l₀-        r₁ = encode r₀-    encode (ListAppend l₀ r₀) =-        TList [ TInt 3, TInt 7, l₁, r₁ ]-      where-        l₁ = encode l₀-        r₁ = encode r₀-    encode (Combine l₀ r₀) =-        TList [ TInt 3, TInt 8, l₁, r₁ ]-      where-        l₁ = encode l₀-        r₁ = encode r₀-    encode (Prefer l₀ r₀) =-        TList [ TInt 3, TInt 9, l₁, r₁ ]-      where-        l₁ = encode l₀-        r₁ = encode r₀-    encode (CombineTypes l₀ r₀) =-        TList [ TInt 3, TInt 10, l₁, r₁ ]-      where-        l₁ = encode l₀-        r₁ = encode r₀-    encode (ImportAlt l₀ r₀) =-        TList [ TInt 3, TInt 11, l₁, r₁ ]-      where-        l₁ = encode l₀-        r₁ = encode r₀-    encode (ListLit _T₀ xs₀)-        | null xs₀  = TList [ TInt 4, _T₁ ]-        | otherwise = TList ([ TInt 4, TNull ] ++ xs₁)-      where-        _T₁ = case _T₀ of-            Nothing -> TNull-            Just t  -> encode t--        xs₁ = map encode (Data.Foldable.toList xs₀)-    encode (OptionalLit _T₀ Nothing) =-        TList [ TInt 5, _T₁ ]-      where-        _T₁ = encode _T₀-    encode (OptionalLit _T₀ (Just t₀)) =-        TList [ TInt 5, _T₁, t₁ ]-      where-        _T₁ = encode _T₀-        t₁  = encode t₀-    encode (Some t₀) =-        TList [ TInt 5, TNull, t₁ ]-      where-        t₁ = encode t₀-    encode (Merge t₀ u₀ Nothing) =-        TList [ TInt 6, t₁, u₁ ]-      where-        t₁ = encode t₀-        u₁ = encode u₀-    encode (Merge t₀ u₀ (Just _T₀)) =-        TList [ TInt 6, t₁, u₁, _T₁ ]-      where-        t₁  = encode t₀-        u₁  = encode u₀-        _T₁ = encode _T₀-    encode (Record xTs₀) =-        TList [ TInt 7, TMap xTs₁ ]-      where-        xTs₁ = do-            (x₀, _T₀) <- Dhall.Map.toList (Dhall.Map.sort xTs₀)-            let x₁  = TString x₀-            let _T₁ = encode _T₀-            return (x₁, _T₁)-    encode (RecordLit xts₀) =-        TList [ TInt 8, TMap xts₁ ]-      where-        xts₁ = do-            (x₀, t₀) <- Dhall.Map.toList (Dhall.Map.sort xts₀)-            let x₁ = TString x₀-            let t₁ = encode t₀-            return (x₁, t₁)-    encode (Field t₀ x) =-        TList [ TInt 9, t₁, TString x ]-      where-        t₁ = encode t₀-    encode (Project t₀ (Left xs₀)) =-        TList ([ TInt 10, t₁ ] ++ xs₁)-      where-        t₁  = encode t₀-        xs₁ = map TString (Dhall.Set.toList xs₀)-    encode (Project t₀ (Right _T₀)) =-        TList [ TInt 10, t₁, TList [ _T₁ ] ]-      where-        _T₁ = encode _T₀-        t₁  = encode t₀-    encode (Union xTs₀) =-        TList [ TInt 11, TMap xTs₁ ]-      where-        xTs₁ = do-            (x₀, mT₀) <- Dhall.Map.toList (Dhall.Map.sort xTs₀)--            let x₁  = TString x₀--            let _T₁ = case mT₀ of-                    Nothing  -> TNull-                    Just _T₀ -> encode _T₀--            return (x₁, _T₁)-    encode (UnionLit x t₀ yTs₀) =-        TList [ TInt 12, TString x, t₁, TMap yTs₁ ]-      where-        t₁ = encode t₀--        yTs₁ = do-            (y₀, mT₀) <- Dhall.Map.toList (Dhall.Map.sort yTs₀)-            let y₁  = TString y₀-            let _T₁ = case mT₀ of-                    Just _T₀ -> encode _T₀-                    Nothing  -> TNull-            return (y₁, _T₁)-    encode (BoolLit b) =-        TBool b-    encode (BoolIf t₀ l₀ r₀) =-        TList [ TInt 14, t₁, l₁, r₁ ]-      where-        t₁ = encode t₀-        l₁ = encode l₀-        r₁ = encode r₀-    encode (NaturalLit n) =-        TList [ TInt 15, TInteger (fromIntegral n) ]-    encode (IntegerLit n) =-        TList [ TInt 16, TInteger n ]-    encode (DoubleLit n64)-        -- cborg always encodes NaN as "7e00"-        | isNaN n64 = THalf n32-        | useHalf   = THalf n32-        | useFloat  = TFloat n32-        | otherwise = TDouble n64-      where-        n32      = double2Float n64-        useFloat = n64 == float2Double n32-        -- the other three cases for Half-floats are 0.0 and the infinities-        useHalf  = or $ fmap (n64 ==) [0.0, infinity, -infinity]-        infinity = 1/0 :: Double-    encode (TextLit (Chunks xys₀ z₀)) =-        TList ([ TInt 18 ] ++ xys₁ ++ [ z₁ ])-      where-        xys₁ = do-            (x₀, y₀) <- xys₀-            let x₁ = TString x₀-            let y₁ = encode y₀-            [ x₁, y₁ ]--        z₁ = TString z₀-    encode (Embed x) =-        encode x-    encode (Let as₀ b₀) =-        TList ([ TInt 25 ] ++ as₁ ++ [ b₁ ])-      where-        as₁ = do-            Binding x mA₀ a₀ <- toList as₀--            let mA₁ = case mA₀ of-                    Nothing  -> TNull-                    Just _A₀ -> encode _A₀--            let a₁ = encode a₀--            [ TString x, mA₁, a₁ ]--        b₁ = encode b₀-    encode (Annot t₀ _T₀) =-        TList [ TInt 26, t₁, _T₁ ]-      where-        t₁  = encode t₀-        _T₁ = encode _T₀-    encode (Note _ e) =-        encode e--instance ToTerm Import where-    encode import_ =-        case importType of-            Remote (URL { scheme = scheme₀, ..}) ->-                TList-                    (   prefix-                    ++  [ TInt scheme₁, using, TString authority ]-                    ++  map TString (reverse components)-                    ++  [ TString file ]-                    ++  (case query    of Nothing -> [ TNull ]; Just q -> [ TString q ])-                    )-              where-                using = case headers of-                    Nothing ->-                        TNull-                    Just h ->-                        encode h--                scheme₁ = case scheme₀ of-                    HTTP  -> 0-                    HTTPS -> 1-                File {..} = path--                Directory {..} = directory--            Local prefix₀ path ->-                    TList-                        (   prefix-                        ++  [ TInt prefix₁ ]-                        ++  map TString components₁-                        ++  [ TString file ]-                        )-              where-                File {..} = path--                Directory {..} = directory--                prefix₁ = case prefix₀ of-                  Absolute -> 2-                  Here     -> 3-                  Parent   -> 4-                  Home     -> 5--                components₁ = reverse components--            Env x ->-                TList (prefix ++ [ TInt 6, TString x ])--            Missing ->-                TList (prefix ++ [ TInt 7 ])-      where-        prefix = [ TInt 24, h, m ]-          where-            h = case hash of-                Nothing ->-                    TNull-                Just digest ->-                    TBytes ("\x12\x20" <> Data.ByteArray.convert digest)--            m = TInt (case importMode of Code -> 0; RawText -> 1)--        Import {..} = import_--        ImportHashed {..} = importHashed---- | Types that can be decoded from a CBOR `Term`-class FromTerm a where-    decode :: Term -> Maybe a--instance FromTerm a => FromTerm (Expr s a) where-    decode (TInt n) =-        return (Var (V "_" (fromIntegral n)))-    decode (TInteger n) =-        return (Var (V "_" n))-    decode (TString "Natural/build") =-        return NaturalBuild-    decode (TString "Natural/fold") =-        return NaturalFold-    decode (TString "Natural/isZero") =-        return NaturalIsZero-    decode (TString "Natural/even") =-        return NaturalEven-    decode (TString "Natural/odd") =-        return NaturalOdd-    decode (TString "Natural/toInteger") =-        return NaturalToInteger-    decode (TString "Natural/show") =-        return NaturalShow-    decode (TString "Integer/toDouble") =-        return IntegerToDouble-    decode (TString "Integer/show") =-        return IntegerShow-    decode (TString "Double/show") =-        return DoubleShow-    decode (TString "List/build") =-        return ListBuild-    decode (TString "List/fold") =-        return ListFold-    decode (TString "List/length") =-        return ListLength-    decode (TString "List/head") =-        return ListHead-    decode (TString "List/last") =-        return ListLast-    decode (TString "List/indexed") =-        return ListIndexed-    decode (TString "List/reverse") =-        return ListReverse-    decode (TString "Optional/fold") =-        return OptionalFold-    decode (TString "Optional/build") =-        return OptionalBuild-    decode (TString "Bool") =-        return Bool-    decode (TString "Optional") =-        return Optional-    decode (TString "None") =-        return None-    decode (TString "Natural") =-        return Natural-    decode (TString "Integer") =-        return Integer-    decode (TString "Double") =-        return Double-    decode (TString "Text") =-        return Text-    decode (TString "Text/show") =-        return TextShow-    decode (TString "List") =-        return List-    decode (TString "Type") =-        return (Const Type)-    decode (TString "Kind") =-        return (Const Kind)-    decode (TString "Sort") =-        return (Const Sort)-    decode (TString "_") =-        empty-    decode (TList [ TString x, TInt n ]) =-        return (Var (V x (fromIntegral n)))-    decode (TList [ TString x, TInteger n ]) =-        return (Var (V x n))-    decode (TList (TInt 0 : f₁ : xs₁)) = do-        f₀  <- decode f₁-        xs₀ <- traverse decode xs₁-        return (foldl App f₀ xs₀)-    decode (TList [ TInt 1, _A₁, b₁ ]) = do-        _A₀ <- decode _A₁-        b₀  <- decode b₁-        return (Lam "_" _A₀ b₀)-    decode (TList [ TInt 1, TString x, _A₁, b₁ ]) = do-        _A₀ <- decode _A₁-        b₀  <- decode b₁-        return (Lam x _A₀ b₀)-    decode (TList [ TInt 2, _A₁, _B₁ ]) = do-        _A₀ <- decode _A₁-        _B₀ <- decode _B₁-        return (Pi "_" _A₀ _B₀)-    decode (TList [ TInt 2, TString x, _A₁, _B₁ ]) = do-        _A₀ <- decode _A₁-        _B₀ <- decode _B₁-        return (Pi x _A₀ _B₀)-    decode (TList [ TInt 3, TInt n, l₁, r₁ ]) = do-        l₀ <- decode l₁-        r₀ <- decode r₁-        op <- case n of-                0  -> return BoolOr-                1  -> return BoolAnd-                2  -> return BoolEQ-                3  -> return BoolNE-                4  -> return NaturalPlus-                5  -> return NaturalTimes-                6  -> return TextAppend-                7  -> return ListAppend-                8  -> return Combine-                9  -> return Prefer-                10 -> return CombineTypes-                11 -> return ImportAlt-                _  -> empty-        return (op l₀ r₀)-    decode (TList [ TInt 4, _T₁ ]) = do-        _T₀ <- decode _T₁-        return (ListLit (Just _T₀) empty)-    decode (TList (TInt 4 : TNull : xs₁ )) = do-        xs₀ <- traverse decode xs₁-        return (ListLit Nothing (Data.Sequence.fromList xs₀))-    decode (TList [ TInt 5, _T₁ ]) = do-        _T₀ <- decode _T₁-        return (OptionalLit _T₀ Nothing)-    decode (TList [ TInt 5, TNull, t₁ ]) = do-        t₀ <- decode t₁-        return (Some t₀)-    decode (TList [ TInt 5, _T₁, t₁ ]) = do-        _T₀ <- decode _T₁-        t₀  <- decode t₁-        return (OptionalLit _T₀ (Just t₀))-    decode (TList [ TInt 6, t₁, u₁ ]) = do-        t₀ <- decode t₁-        u₀ <- decode u₁-        return (Merge t₀ u₀ Nothing)-    decode (TList [ TInt 6, t₁, u₁, _T₁ ]) = do-        t₀  <- decode t₁-        u₀  <- decode u₁-        _T₀ <- decode _T₁-        return (Merge t₀ u₀ (Just _T₀))-    decode (TList [ TInt 7, TMap xTs₁ ]) = do-        let process (TString x, _T₁) = do-                _T₀ <- decode _T₁--                return (x, _T₀)-            process _ =-                empty--        xTs₀ <- traverse process xTs₁--        return (Record (Dhall.Map.fromList xTs₀))-    decode (TList [ TInt 8, TMap xts₁ ]) = do-        let process (TString x, t₁) = do-               t₀ <- decode t₁--               return (x, t₀)-            process _ =-                empty--        xts₀ <- traverse process xts₁--        return (RecordLit (Dhall.Map.fromList xts₀))-    decode (TList [ TInt 9, t₁, TString x ]) = do-        t₀ <- decode t₁--        return (Field t₀ x)-    decode (TList (TInt 10 : t₁ : xs₁)) = do-        t₀ <- decode t₁--        let expectString (TString x) = return x-            expectString  _          = empty--        let decodeLeft = do-                strings <- traverse expectString xs₁--                return (Left (Dhall.Set.fromList strings))--        let decodeRight =-                case xs₁ of-                    [ TList [ _T₁ ] ] -> do-                        _T₀ <- decode _T₁--                        return (Right _T₀)-                    _ -> do-                        empty--        xs₀ <- decodeLeft <|> decodeRight--        return (Project t₀ xs₀)-    decode (TList [ TInt 11, TMap xTs₁ ]) = do-        let process (TString x, _T₁) = do-                mT₀ <- case _T₁ of-                    TNull -> return Nothing-                    _     -> fmap Just (decode _T₁)--                return (x, mT₀)-            process _ =-                empty--        xTs₀ <- traverse process xTs₁--        return (Union (Dhall.Map.fromList xTs₀))-    decode (TList [ TInt 12, TString x, t₁, TMap yTs₁ ]) = do-        t₀ <- decode t₁--        let process (TString y, _T₁) = do-                _T₀ <- case _T₁ of-                    TNull -> return Nothing-                    _     -> fmap Just (decode _T₁)--                return (y, _T₀)-            process _ =-                empty--        yTs₀ <- traverse process yTs₁--        return (UnionLit x t₀ (Dhall.Map.fromList yTs₀))-    decode (TBool b) = do-        return (BoolLit b)-    decode (TList [ TInt 14, t₁, l₁, r₁ ]) = do-        t₀ <- decode t₁-        l₀ <- decode l₁-        r₀ <- decode r₁--        return (BoolIf t₀ l₀ r₀)-    decode (TList [ TInt 15, TInt n ]) = do-        return (NaturalLit (fromIntegral n))-    decode (TList [ TInt 15, TInteger n ]) = do-        return (NaturalLit (fromInteger n))-    decode (TList [ TInt 16, TInt n ]) = do-        return (IntegerLit (fromIntegral n))-    decode (TList [ TInt 16, TInteger n ]) = do-        return (IntegerLit n)-    decode (THalf n) = do-        return (DoubleLit (float2Double n))-    decode (TFloat n) = do-        return (DoubleLit (float2Double n))-    decode (TDouble n) = do-        return (DoubleLit n)-    decode (TList (TInt 18 : xs)) = do-        let process (TString x : y₁ : zs) = do-                y₀ <- decode y₁--                ~(xys, z) <- process zs--                return ((x, y₀) : xys, z)-            process [ TString z ] = do-                return ([], z)-            process _ = do-                empty--        (xys, z) <- process xs--        return (TextLit (Chunks xys z))-    decode e@(TList (TInt 24 : _)) = fmap Embed (decode e)-    decode (TList (TInt 25 : xs)) = do-        let process (TString x : _A₁ : a₁ : ls₁) = do-                mA₀ <- case _A₁ of-                    TNull -> return Nothing-                    _     -> fmap Just (decode _A₁)--                a₀  <- decode a₁--                let binding = Binding x mA₀ a₀--                case ls₁ of-                    [ b₁ ] -> do-                        b₀ <- decode b₁--                        return (Let (binding :| []) b₀)-                    _ -> do-                        Let (l₀ :| ls₀) b₀ <- process ls₁--                        return (Let (binding :| (l₀ : ls₀)) b₀)-            process _ = do-                empty--        process xs-    decode (TList [ TInt 26, t₁, _T₁ ]) = do-        t₀  <- decode t₁-        _T₀ <- decode _T₁-        return (Annot t₀ _T₀)-    decode _ =-        empty--instance FromTerm Import where-    decode (TList (TInt 24 : h : TInt mode : TInt n : xs)) = do-        hash <- case h of-            TNull -> do-                return Nothing--            TBytes bytes -> do-                let (prefix, suffix) = Data.ByteString.splitAt 2 bytes--                case prefix of-                    "\x12\x20" -> return ()-                    _          -> empty--                digest <- case Crypto.Hash.digestFromByteString suffix of-                    Nothing     -> empty-                    Just digest -> return digest--                return (Just digest)--            _ -> do-                empty--        importMode <- case mode of-            0 -> return Code-            1 -> return RawText-            _ -> empty--        let remote scheme = do-                let process [ TString file, q ] = do-                        query <- case q of-                            TNull     -> return Nothing-                            TString x -> return (Just x)-                            _         -> empty-                        return ([], file, query)-                    process (TString path : ys) = do-                        (paths, file, query) <- process ys-                        return (path : paths, file, query)-                    process _ = do-                        empty--                (headers, authority, paths, file, query) <- case xs of-                    headers₀ : TString authority : ys -> do-                        headers₁ <- case headers₀ of-                            TNull -> do-                                return Nothing-                            _     -> do-                                headers <- decode headers₀--                                return (Just headers)-                        (paths, file, query) <- process ys-                        return (headers₁, authority, paths, file, query)-                    _ -> do-                        empty--                let components = reverse paths-                let directory  = Directory {..}-                let path       = File {..}--                return (Remote (URL {..}))--        let local prefix = do-                let process [ TString file ] = do-                        return ([], file)-                    process (TString path : ys) = do-                        (paths, file) <- process ys-                        return (path : paths, file)-                    process _ =-                        empty--                (paths, file) <- process xs--                let components = reverse paths-                let directory  = Directory {..}--                return (Local prefix (File {..}))--        let env = do-                case xs of-                    [ TString x ] -> return (Env x)-                    _             -> empty--        let missing = return Missing--        importType <- case n of-            0 -> remote HTTP-            1 -> remote HTTPS-            2 -> local Absolute-            3 -> local Here-            4 -> local Parent-            5 -> local Home-            6 -> env-            7 -> missing-            _ -> empty--        let importHashed = ImportHashed {..}--        return (Import {..})--    decode _ = empty--strip55799Tag :: Term -> Term-strip55799Tag term =-    case term of-        TInt a ->-            TInt a-        TInteger a ->-            TInteger a-        TBytes a ->-            TBytes a-        TBytesI a ->-            TBytesI a-        TString a ->-            TString a-        TStringI a ->-            TStringI a-        TList as ->-            TList (fmap strip55799Tag as)-        TListI as ->-            TListI (fmap strip55799Tag as)-        TMap as ->-            TMap (fmap adapt as)-          where-            adapt (a, b) = (strip55799Tag a, strip55799Tag b)-        TMapI as ->-            TMapI (fmap adapt as)-          where-            adapt (a, b) = (strip55799Tag a, strip55799Tag b)-        TTagged 55799 b ->-            strip55799Tag b-        TTagged a b->-            TTagged a (strip55799Tag b)-        TBool a ->-            TBool a-        TNull ->-            TNull-        TSimple a ->-            TSimple a-        THalf a ->-            THalf a-        TFloat a ->-            TFloat a-        TDouble a ->-            TDouble a---- | Encode a Dhall expression as a CBOR `Term`-encodeExpression :: Expr s Import -> Term-encodeExpression = encode---- | Decode a Dhall expression from a CBOR `Term`-decodeExpression :: Term -> Either DecodingFailure (Expr s Import)-decodeExpression term =-    case decodeWithoutVersion <|> decodeWithVersion of-        Just expression -> Right expression-        Nothing         -> Left (CBORIsNotDhall term)-  where-    strippedTerm = strip55799Tag term-    -- This is the behavior specified by the standard-    decodeWithoutVersion = decode strippedTerm--    -- For backwards compatibility with older expressions that have a version-    -- tag to ease the migration-    decodeWithVersion = do-        TList [ TString _, taggedTerm ] <- return strippedTerm-        decode taggedTerm--data DecodingFailure = CBORIsNotDhall Term-    deriving (Eq)--instance Exception DecodingFailure--_ERROR :: String-_ERROR = "\ESC[1;31mError\ESC[0m"--instance Show DecodingFailure where-    show (CBORIsNotDhall term) =-            _ERROR <> ": Cannot decode CBOR to Dhall\n"-        <>  "\n"-        <>  "The following CBOR expression does not encode a valid Dhall expression\n"-        <>  "\n"-        <>  "↳ " <> show term <> "\n"+{-# LANGUAGE BangPatterns      #-}+{-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards   #-}+{-# LANGUAGE ViewPatterns      #-}++{-# OPTIONS_GHC -fno-warn-orphans #-}++{-| This module contains logic for converting Dhall expressions to and from+    CBOR expressions which can in turn be converted to and from a binary+    representation+-}++module Dhall.Binary+    ( -- * Encoding and decoding+      encodeExpression+    , decodeExpression++      -- * Exceptions+    , DecodingFailure(..)+    ) where++import Codec.CBOR.Decoding  (Decoder, TokenType (..))+import Codec.CBOR.Encoding  (Encoding)+import Codec.Serialise      (Serialise (decode, encode))+import Control.Applicative  (empty, (<|>))+import Control.Exception    (Exception)+import Data.ByteString.Lazy (ByteString)+import Dhall.Syntax+    ( Binding (..)+    , Chunks (..)+    , Const (..)+    , DhallDouble (..)+    , Directory (..)+    , Expr (..)+    , File (..)+    , FilePrefix (..)+    , FunctionBinding (..)+    , Import (..)+    , ImportHashed (..)+    , ImportMode (..)+    , ImportType (..)+    , MultiLet (..)+    , PreferAnnotation (..)+    , RecordField (..)+    , Scheme (..)+    , URL (..)+    , Var (..)+    , WithComponent (..)+    )++import Data.Foldable (toList)+import Data.Ratio    ((%))+import Data.Void     (Void, absurd)+import GHC.Float     (double2Float, float2Double)+import Numeric.Half  (fromHalf, toHalf)+import Prelude       hiding (exponent)++import qualified Codec.CBOR.ByteArray+import qualified Codec.CBOR.Decoding   as Decoding+import qualified Codec.CBOR.Encoding   as Encoding+import qualified Codec.CBOR.Read       as Read+import qualified Codec.Serialise       as Serialise+import qualified Data.ByteString+import qualified Data.ByteString.Lazy+import qualified Data.ByteString.Short+import qualified Data.Foldable         as Foldable+import qualified Data.List.NonEmpty    as NonEmpty+import qualified Data.Sequence+import qualified Data.Time             as Time+import qualified Dhall.Crypto+import qualified Dhall.Map+import qualified Dhall.Syntax          as Syntax+import qualified Text.Printf           as Printf++{-| Convert a function applied to multiple arguments to the base function and+    the list of arguments+-}+unApply :: Expr s a -> (Expr s a, [Expr s a])+unApply e₀ = (baseFunction₀, diffArguments₀ [])+  where+    ~(baseFunction₀, diffArguments₀) = go e₀++    go (App f a) = (baseFunction, diffArguments . (a :))+      where+        ~(baseFunction, diffArguments) = go f++    go (Note _ e) = go e++    go baseFunction = (baseFunction, id)++decodeExpressionInternal :: (Int -> Decoder s a) -> Decoder s (Expr t a)+decodeExpressionInternal decodeEmbed = go+  where+    go = do+        let die message = fail ("Dhall.Binary.decodeExpressionInternal: " <> message)++        tokenType₀ <- Decoding.peekTokenType++        case tokenType₀ of+            TypeUInt -> do+                !n <- fromIntegral <$> Decoding.decodeWord++                return (Var (V "_" n))++            TypeUInt64 -> do+                !n <- fromIntegral <$> Decoding.decodeWord64++                return (Var (V "_" n))++            TypeFloat16 -> do+                !n <- float2Double <$> Decoding.decodeFloat++                return (DoubleLit (DhallDouble n))++            TypeFloat32 -> do+                !n <- float2Double <$> Decoding.decodeFloat++                return (DoubleLit (DhallDouble n))++            TypeFloat64 -> do+                !n <- Decoding.decodeDouble++                return (DoubleLit (DhallDouble n))++            TypeBool -> do+                !b <- Decoding.decodeBool++                return (BoolLit b)++            TypeString -> do+                !ba <- Decoding.decodeUtf8ByteArray++                let sb = Codec.CBOR.ByteArray.toShortByteString ba++                case Data.ByteString.Short.length sb of+                    4  | sb == "Bool"              -> return Bool+                       | sb == "Date"              -> return Date+                       | sb == "List"              -> return List+                       | sb == "None"              -> return None+                       | sb == "Text"              -> return Text+                       | sb == "Time"              -> return Time+                       | sb == "Type"              -> return (Const Type)+                       | sb == "Kind"              -> return (Const Kind)+                       | sb == "Sort"              -> return (Const Sort)+                    5  | sb == "Bytes"             -> return Bytes+                    6  | sb == "Double"            -> return Double+                    7  | sb == "Integer"           -> return Integer+                       | sb == "Natural"           -> return Natural+                    8  | sb == "Optional"          -> return Optional+                       | sb == "TimeZone"          -> return TimeZone+                    9  | sb == "Date/show"         -> return DateShow+                       | sb == "List/fold"         -> return ListFold+                       | sb == "List/head"         -> return ListHead+                       | sb == "List/last"         -> return ListLast+                       | sb == "Text/show"         -> return TextShow+                       | sb == "Time/show"         -> return TimeShow+                    10 | sb == "List/build"        -> return ListBuild+                    11 | sb == "Double/show"       -> return DoubleShow+                       | sb == "List/length"       -> return ListLength+                       | sb == "Natural/odd"       -> return NaturalOdd+                    12 | sb == "Integer/show"      -> return IntegerShow+                       | sb == "List/indexed"      -> return ListIndexed+                       | sb == "List/reverse"      -> return ListReverse+                       | sb == "Natural/even"      -> return NaturalEven+                       | sb == "Natural/fold"      -> return NaturalFold+                       | sb == "Natural/show"      -> return NaturalShow+                       | sb == "Text/replace"      -> return TextReplace+                    13 | sb == "Integer/clamp"     -> return IntegerClamp+                       | sb == "Natural/build"     -> return NaturalBuild+                       | sb == "TimeZone/show"     -> return TimeZoneShow+                    14 | sb == "Integer/negate"    -> return IntegerNegate+                       | sb == "Natural/isZero"    -> return NaturalIsZero+                    16 | sb == "Integer/toDouble"  -> return IntegerToDouble+                       | sb == "Natural/subtract"  -> return NaturalSubtract+                    17 | sb == "Natural/toInteger" -> return NaturalToInteger+                    _                              -> die ("Unrecognized built-in: " <> show sb)++            TypeListLen -> do+                len <- Decoding.decodeListLen++                case len of+                    0 -> die "Missing tag"+                    _ -> return ()++                tokenType₁ <- Decoding.peekTokenType++                case tokenType₁ of+                    TypeString -> do+                        x <- Decoding.decodeString++                        if x == "_"+                            then die "Non-standard encoding of an α-normalized variable"+                            else return ()++                        tokenType₂ <- Decoding.peekTokenType++                        case tokenType₂ of+                            TypeUInt -> do+                                !n <- fromIntegral <$> Decoding.decodeWord++                                return (Var (V x n))++                            TypeUInt64 -> do+                                !n <- fromIntegral <$> Decoding.decodeWord64++                                return (Var (V x n))++                            _ ->+                                die ("Unexpected token type for variable index: " <> show tokenType₂)++                    TypeUInt -> do+                        tag <- Decoding.decodeWord++                        case tag of+                            0 -> do+                                !f <- go++                                let loop n !acc+                                        | n <= 0    = return acc+                                        | otherwise = do+                                              !x <- go+                                              loop (n - 1) (App acc x)++                                let nArgs = len - 2++                                if nArgs <= 0+                                    then die "Non-standard encoding of a function with no arguments"+                                    else loop nArgs f++                            1 ->+                                case len of+                                    3 -> do+                                        _A <- go++                                        b <- go++                                        return (Lam mempty (Syntax.makeFunctionBinding "_" _A) b)++                                    4 -> do+                                        x <- Decoding.decodeString++                                        if x == "_"+                                            then die "Non-standard encoding of a λ expression"+                                            else return ()++                                        _A <- go++                                        b <- go++                                        return (Lam mempty (Syntax.makeFunctionBinding x _A) b)++                                    _ ->+                                        die ("Incorrect number of tokens used to encode a λ expression: " <> show len)++                            2 ->+                                case len of+                                    3 -> do+                                        _A <- go++                                        _B <- go++                                        return (Pi mempty "_" _A _B)++                                    4 -> do+                                        x <- Decoding.decodeString++                                        if x == "_"+                                            then die "Non-standard encoding of a ∀ expression"+                                            else return ()++                                        _A <- go++                                        _B <- go++                                        return (Pi mempty x _A _B)++                                    _ ->+                                        die ("Incorrect number of tokens used to encode a ∀ expression: " <> show len)++                            3 -> do+                                opcode <- Decoding.decodeWord++                                op <- case opcode of+                                    0  -> return BoolOr+                                    1  -> return BoolAnd+                                    2  -> return BoolEQ+                                    3  -> return BoolNE+                                    4  -> return NaturalPlus+                                    5  -> return NaturalTimes+                                    6  -> return TextAppend+                                    7  -> return ListAppend+                                    8  -> return (Combine mempty Nothing)+                                    9  -> return (Prefer mempty PreferFromSource)+                                    10 -> return (CombineTypes mempty)+                                    11 -> return ImportAlt+                                    12 -> return (Equivalent mempty)+                                    13 -> return RecordCompletion+                                    _  -> die ("Unrecognized operator code: " <> show opcode)++                                l <- go++                                r <- go++                                return (op l r)++                            4 ->+                                case len of+                                    2 -> do+                                        _T <- go++                                        return (ListLit (Just (App List _T)) empty)++                                    _ -> do+                                        Decoding.decodeNull++                                        xs <- Data.Sequence.replicateA (len - 2) go+                                        return (ListLit Nothing xs)++                            5 -> do+                                Decoding.decodeNull++                                t <- go++                                return (Some t)++                            6 -> do+                                t <- go++                                u <- go++                                case len of+                                    3 ->+                                        return (Merge t u Nothing)++                                    4 -> do+                                        _T <- go++                                        return (Merge t u (Just _T))++                                    _ ->+                                        die ("Incorrect number of tokens used to encode a `merge` expression: " <> show len)++                            7 -> do+                                mapLength <- Decoding.decodeMapLen++                                xTs <- replicateDecoder mapLength $ do+                                    x <- Decoding.decodeString++                                    _T <- go++                                    return (x, Syntax.makeRecordField _T)++                                return (Record (Dhall.Map.fromList xTs))++                            8 -> do+                                mapLength <- Decoding.decodeMapLen++                                xts <- replicateDecoder mapLength $ do+                                    x <- Decoding.decodeString++                                    t <- go++                                    return (x, Syntax.makeRecordField t)++                                return (RecordLit (Dhall.Map.fromList xts))++                            9 -> do+                                t <- go++                                x <- Decoding.decodeString++                                return (Field t (Syntax.makeFieldSelection x))++                            10 -> do+                                t <- go++                                xs <- case len of+                                    3 -> do+                                        tokenType₂ <- Decoding.peekTokenType++                                        case tokenType₂ of+                                            TypeListLen -> do+                                                _ <- Decoding.decodeListLen++                                                _T <- go++                                                return (Right _T)++                                            TypeString -> do+                                                x <- Decoding.decodeString+                                                return (Left [x])++                                            _ ->+                                                die ("Unexpected token type for projection: " <> show tokenType₂)++                                    _ -> do+                                        xs <- replicateDecoder (len - 2) Decoding.decodeString++                                        return (Left xs)++                                return (Project t xs)++                            11 -> do+                                mapLength <- Decoding.decodeMapLen++                                xTs <- replicateDecoder mapLength $ do+                                    x <- Decoding.decodeString++                                    tokenType₂ <- Decoding.peekTokenType++                                    mT <- case tokenType₂ of+                                        TypeNull -> do+                                            Decoding.decodeNull++                                            return Nothing++                                        _ -> do+                                            _T <- go++                                            return (Just _T)++                                    return (x, mT)++                                return (Union (Dhall.Map.fromList xTs))++                            14 -> do+                                t <- go++                                l <- go++                                r <- go++                                return (BoolIf t l r)++                            15 -> do+                                tokenType₂ <- Decoding.peekTokenType++                                case tokenType₂ of+                                    TypeUInt -> do+                                        !n <- fromIntegral <$> Decoding.decodeWord++                                        return (NaturalLit n)++                                    TypeUInt64 -> do+                                        !n <- fromIntegral <$> Decoding.decodeWord64++                                        return (NaturalLit n)++                                    TypeInteger -> do+                                        !n <- fromIntegral <$> Decoding.decodeInteger+                                        return (NaturalLit n)++                                    _ ->+                                        die ("Unexpected token type for Natural literal: " <> show tokenType₂)++                            16 -> do+                                tokenType₂ <- Decoding.peekTokenType++                                case tokenType₂ of+                                    TypeUInt -> do+                                        !n <- fromIntegral <$> Decoding.decodeWord++                                        return (IntegerLit n)++                                    TypeUInt64 -> do+                                        !n <- fromIntegral <$> Decoding.decodeWord64++                                        return (IntegerLit n)++                                    TypeNInt -> do+                                        !n <- fromIntegral <$> Decoding.decodeNegWord++                                        return (IntegerLit $! (-1 - n))++                                    TypeNInt64 -> do+                                        !n <- fromIntegral <$> Decoding.decodeNegWord64++                                        return (IntegerLit $! (-1 - n))+                                    TypeInteger -> do+                                        n <- Decoding.decodeInteger+                                        return (IntegerLit n)++                                    _ ->+                                        die ("Unexpected token type for Integer literal: " <> show tokenType₂)++                            18 -> do+                                xys <- replicateDecoder ((len - 2) `quot` 2) $ do+                                    x <- Decoding.decodeString++                                    y <- go++                                    return (x, y)++                                z <- Decoding.decodeString++                                return (TextLit (Chunks xys z))++                            19 -> do+                                t <- go++                                return (Assert t)++                            24 ->+                                fmap Embed (decodeEmbed len)++                            25 -> do+                                bindings <- replicateDecoder ((len - 2) `quot` 3) $ do+                                    x <- Decoding.decodeString++                                    tokenType₂ <- Decoding.peekTokenType++                                    mA <- case tokenType₂ of+                                        TypeNull -> do+                                            Decoding.decodeNull++                                            return Nothing++                                        _ -> do+                                            _A <- go++                                            return (Just (Nothing, _A))++                                    a <- go++                                    return (Binding Nothing x Nothing mA Nothing a)++                                b <- go++                                return (foldr Let b bindings)++                            26 -> do+                                t <- go++                                _T <- go++                                return (Annot t _T)++                            27 -> do+                                t <- go++                                mT <- case len of+                                    2 ->+                                        return Nothing++                                    3 -> do+                                        _T <- go++                                        return (Just _T)++                                    _ ->+                                        die ("Incorrect number of tokens used to encode a type annotation: " <> show len)++                                return (ToMap t mT)++                            28 -> do+                                _T <- go++                                return (ListLit (Just _T) empty)++                            29 -> do+                                l <- go++                                n <- Decoding.decodeListLen++                                let decodeWithComponent = do+                                        tokenType₂ <- Decoding.peekTokenType+                                        case tokenType₂ of+                                            TypeString -> do+                                                fmap WithLabel Decoding.decodeString+                                            _ -> do+                                                m <- Decoding.decodeInt++                                                case m of+                                                    0 -> return WithQuestion+                                                    _ -> die ("Unexpected integer encoding a with expression: " <> show n)+                                ks₀ <- replicateDecoder n decodeWithComponent++                                ks₁ <- case NonEmpty.nonEmpty ks₀ of+                                    Nothing ->+                                        die "0 field labels in decoded with expression"+                                    Just ks₁ ->+                                        return ks₁++                                r <- go++                                return (With l ks₁ r)++                            30 -> do+                                _YYYY <- Decoding.decodeInt+                                _MM   <- Decoding.decodeInt+                                _HH   <- Decoding.decodeInt++                                case Time.fromGregorianValid (fromIntegral _YYYY) _MM _HH of+                                    Nothing ->+                                        die "Invalid date"+                                    Just day ->+                                        return (DateLiteral day)+                            31 -> do+                                hh <- Decoding.decodeInt+                                mm <- Decoding.decodeInt+                                tag₂ <- Decoding.decodeTag++                                case tag₂ of+                                    4 -> do+                                        return ()+                                    _ -> do+                                        die ("Unexpected tag for decimal fraction: " <> show tag)+                                n <- Decoding.decodeListLen++                                case n of+                                    2 -> do+                                        return ()+                                    _ -> do+                                        die ("Invalid list length for decimal fraction: " <> show n)++                                exponent <- Decoding.decodeInt++                                tokenType₂ <- Decoding.peekTokenType++                                mantissa <- case tokenType₂ of+                                    TypeUInt -> do+                                        fromIntegral <$> Decoding.decodeWord++                                    TypeUInt64 -> do+                                        fromIntegral <$> Decoding.decodeWord64++                                    TypeNInt -> do+                                        !i <- fromIntegral <$> Decoding.decodeNegWord++                                        return (-1 - i)++                                    TypeNInt64 -> do+                                        !i <- fromIntegral <$> Decoding.decodeNegWord64++                                        return (-1 - i)+                                    TypeInteger -> do+                                        Decoding.decodeInteger+                                    _ ->+                                        die ("Unexpected token type for mantissa: " <> show tokenType₂)+                                let precision = fromIntegral (negate exponent)++                                let ss = fromRational (mantissa % (10 ^ precision))++                                return (TimeLiteral (Time.TimeOfDay hh mm ss) precision)+                            32 -> do+                                b   <- Decoding.decodeBool+                                _HH <- Decoding.decodeInt+                                _MM <- Decoding.decodeInt++                                let sign = if b then id else negate++                                let minutes = sign (_HH * 60 + _MM)++                                return (TimeZoneLiteral (Time.TimeZone minutes False ""))++                            33 -> do+                                b <- Decoding.decodeBytes++                                return (BytesLit b)++                            34 -> do+                                t <- go+                                return (ShowConstructor t)+                            _ ->+                                die ("Unexpected tag: " <> show tag)++                    _ ->+                        die ("Unexpected tag type: " <> show tokenType₁)++            _ ->+                die ("Unexpected initial token: " <> show tokenType₀)++encodeExpressionInternal :: (a -> Encoding) -> Expr Void a -> Encoding+encodeExpressionInternal encodeEmbed = go+  where+    go e = case e of+        Var (V "_" n) ->+            Encoding.encodeInt n++        Var (V x n) ->+                Encoding.encodeListLen 2+            <>  Encoding.encodeString x+            <>  Encoding.encodeInt n++        NaturalBuild ->+            Encoding.encodeUtf8ByteArray "Natural/build"++        NaturalFold ->+            Encoding.encodeUtf8ByteArray "Natural/fold"++        NaturalIsZero ->+            Encoding.encodeUtf8ByteArray "Natural/isZero"++        NaturalEven ->+            Encoding.encodeUtf8ByteArray "Natural/even"++        NaturalOdd ->+            Encoding.encodeUtf8ByteArray "Natural/odd"++        NaturalToInteger ->+            Encoding.encodeUtf8ByteArray "Natural/toInteger"++        NaturalShow ->+            Encoding.encodeUtf8ByteArray "Natural/show"++        NaturalSubtract ->+            Encoding.encodeUtf8ByteArray "Natural/subtract"++        IntegerToDouble ->+            Encoding.encodeUtf8ByteArray "Integer/toDouble"++        IntegerClamp ->+            Encoding.encodeUtf8ByteArray "Integer/clamp"++        IntegerNegate ->+            Encoding.encodeUtf8ByteArray "Integer/negate"++        IntegerShow ->+            Encoding.encodeUtf8ByteArray "Integer/show"++        DoubleShow ->+            Encoding.encodeUtf8ByteArray "Double/show"++        ListBuild ->+            Encoding.encodeUtf8ByteArray "List/build"++        ListFold ->+            Encoding.encodeUtf8ByteArray "List/fold"++        ListLength ->+            Encoding.encodeUtf8ByteArray "List/length"++        ListHead ->+            Encoding.encodeUtf8ByteArray "List/head"++        ListLast ->+            Encoding.encodeUtf8ByteArray "List/last"++        ListIndexed ->+            Encoding.encodeUtf8ByteArray "List/indexed"++        ListReverse ->+            Encoding.encodeUtf8ByteArray "List/reverse"++        Bool ->+            Encoding.encodeUtf8ByteArray "Bool"++        Bytes ->+            Encoding.encodeUtf8ByteArray "Bytes"++        Optional ->+            Encoding.encodeUtf8ByteArray "Optional"++        None ->+            Encoding.encodeUtf8ByteArray "None"++        Natural ->+            Encoding.encodeUtf8ByteArray "Natural"++        Integer ->+            Encoding.encodeUtf8ByteArray "Integer"++        Double ->+            Encoding.encodeUtf8ByteArray "Double"++        Text ->+            Encoding.encodeUtf8ByteArray "Text"++        TextReplace ->+            Encoding.encodeUtf8ByteArray "Text/replace"++        TextShow ->+            Encoding.encodeUtf8ByteArray "Text/show"++        Date ->+            Encoding.encodeUtf8ByteArray "Date"++        DateShow ->+            Encoding.encodeUtf8ByteArray "Date/show"++        Time ->+            Encoding.encodeUtf8ByteArray "Time"++        TimeShow ->+            Encoding.encodeUtf8ByteArray "Time/show"++        TimeZone ->+            Encoding.encodeUtf8ByteArray "TimeZone"++        TimeZoneShow ->+            Encoding.encodeUtf8ByteArray "TimeZone/show"++        List ->+            Encoding.encodeUtf8ByteArray "List"++        Const Type ->+            Encoding.encodeUtf8ByteArray "Type"++        Const Kind ->+            Encoding.encodeUtf8ByteArray "Kind"++        Const Sort ->+            Encoding.encodeUtf8ByteArray "Sort"++        a@App{} ->+            encodeListN+                (2 + length arguments)+                ( Encoding.encodeInt 0+                : go function+                : map go arguments+                )+          where+            (function, arguments) = unApply a++        Lam _ (FunctionBinding { functionBindingVariable = "_", functionBindingAnnotation = _A }) b ->+            encodeList3+                (Encoding.encodeInt 1)+                (go _A)+                (go b)++        Lam _ (FunctionBinding { functionBindingVariable = x, functionBindingAnnotation = _A }) b ->+            encodeList4+                (Encoding.encodeInt 1)+                (Encoding.encodeString x)+                (go _A)+                (go b)++        Pi _ "_" _A _B ->+            encodeList3+                (Encoding.encodeInt 2)+                (go _A)+                (go _B)++        Pi _ x _A _B ->+            encodeList4+                (Encoding.encodeInt 2)+                (Encoding.encodeString x)+                (go _A)+                (go _B)++        BoolOr l r ->+            encodeOperator 0 l r++        BoolAnd l r ->+            encodeOperator 1 l r++        BoolEQ l r ->+            encodeOperator 2 l r++        BoolNE l r ->+            encodeOperator 3 l r++        BytesLit b ->+            encodeList2+                (Encoding.encodeInt 33)+                (Encoding.encodeBytes b)++        NaturalPlus l r ->+            encodeOperator 4 l r++        NaturalTimes l r ->+            encodeOperator 5 l r++        TextAppend l r ->+            encodeOperator 6 l r++        ListAppend l r ->+            encodeOperator 7 l r++        Combine _ _ l r ->+            encodeOperator 8 l r++        Prefer _ _ l r ->+            encodeOperator 9 l r++        CombineTypes _ l r ->+            encodeOperator 10 l r++        ImportAlt l r ->+            encodeOperator 11 l r++        Equivalent _ l r ->+            encodeOperator 12 l r++        RecordCompletion l r ->+            encodeOperator 13 l r++        ListLit _T₀ xs+            | null xs ->+                encodeList2 (Encoding.encodeInt label) _T₁+            | otherwise ->+                encodeListN+                    (2 + length xs)+                    ( Encoding.encodeInt 4+                    : Encoding.encodeNull+                    : map go (Data.Foldable.toList xs)+                    )+          where+            (label, _T₁) = case _T₀ of+                Nothing           -> (4 , Encoding.encodeNull)+                Just (App List t) -> (4 , go t               )+                Just  t           -> (28, go t               )++        Some t ->+            encodeList3+                (Encoding.encodeInt 5)+                Encoding.encodeNull+                (go t)++        Merge t u Nothing ->+            encodeList3+                (Encoding.encodeInt 6)+                (go t)+                (go u)++        Merge t u (Just _T) ->+            encodeList4+                (Encoding.encodeInt 6)+                (go t)+                (go u)+                (go _T)++        Record xTs ->+            encodeList2+                (Encoding.encodeInt 7)+                (encodeMapWith (go . recordFieldValue) xTs)++        RecordLit xts ->+            encodeList2+                (Encoding.encodeInt 8)+                (encodeMapWith (go. recordFieldValue) xts)++        Field t (Syntax.fieldSelectionLabel -> x) ->+            encodeList3+                (Encoding.encodeInt 9)+                (go t)+                (Encoding.encodeString x)++        Project t (Left xs) ->+            encodeListN+                (2 + length xs)+                ( Encoding.encodeInt 10+                : go t+                : map Encoding.encodeString xs+                )++        Project t (Right _T) ->+            encodeList3+                (Encoding.encodeInt 10)+                (go t)+                (encodeList1 (go _T))++        Union xTs ->+            encodeList2+                (Encoding.encodeInt 11)+                (encodeMapWith encodeValue xTs)+          where+            encodeValue  Nothing  = Encoding.encodeNull+            encodeValue (Just _T) = go _T++        BoolLit b ->+            Encoding.encodeBool b++        BoolIf t l r ->+            encodeList4+                (Encoding.encodeInt 14)+                (go t)+                (go l)+                (go r)++        NaturalLit n ->+            encodeList2+                (Encoding.encodeInt 15)+                (Encoding.encodeInteger (fromIntegral n))++        IntegerLit n ->+            encodeList2+                (Encoding.encodeInt 16)+                (Encoding.encodeInteger (fromIntegral n))++        DoubleLit (DhallDouble n64)+            | useHalf   -> Encoding.encodeFloat16 n32+            | useFloat  -> Encoding.encodeFloat n32+            | otherwise -> Encoding.encodeDouble n64+          where+            n32 = double2Float n64++            n16 = toHalf n32++            useFloat = n64 == float2Double n32++            useHalf = n64 == (float2Double $ fromHalf n16)++        -- Fast path for the common case of an uninterpolated string+        TextLit (Chunks [] z) ->+            encodeList2+                (Encoding.encodeInt 18)+                (Encoding.encodeString z)++        TextLit (Chunks xys z) ->+            encodeListN+                (2 + 2 * length xys)+                ( Encoding.encodeInt 18+                : concatMap encodePair xys ++ [ Encoding.encodeString z ]+                )+          where+            encodePair (x, y) = [ Encoding.encodeString x, go y ]++        Assert t ->+            encodeList2+                (Encoding.encodeInt 19)+                (go t)++        Embed x ->+            encodeEmbed x++        Let a₀ b₀ ->+            encodeListN+                (2 + 3 * length as)+                ( Encoding.encodeInt 25+                : concatMap encodeBinding (toList as) ++ [ go b₁ ]+                )+          where+            MultiLet as b₁ = Syntax.multiLet a₀ b₀++            encodeBinding (Binding _ x _ mA₀ _ a) =+                [ Encoding.encodeString x+                , mA₁+                , go a+                ]+              where+                mA₁ = case mA₀ of+                    Nothing      -> Encoding.encodeNull+                    Just (_, _A) -> go _A++        Annot t _T ->+            encodeList3+                (Encoding.encodeInt 26)+                (go t)+                (go _T)++        ToMap t Nothing ->+            encodeList2+                (Encoding.encodeInt 27)+                (go t)++        ToMap t (Just _T) ->+            encodeList3+                (Encoding.encodeInt 27)+                (go t)+                (go _T)++        With l ks r ->+            encodeList4+                (Encoding.encodeInt 29)+                (go l)+                (encodeList (fmap encodeWithComponent ks))+                (go r)+          where+            encodeWithComponent  WithQuestion  = Encoding.encodeInt 0+            encodeWithComponent (WithLabel k ) = Encoding.encodeString k++        DateLiteral day ->+            encodeList4+                (Encoding.encodeInt 30)+                (Encoding.encodeInt (fromInteger _YYYY))+                (Encoding.encodeInt _MM)+                (Encoding.encodeInt _DD)+          where+            (_YYYY, _MM, _DD) = Time.toGregorian day++        TimeLiteral (Time.TimeOfDay hh mm ss) precision ->+            encodeList4+                (Encoding.encodeInt 31)+                (Encoding.encodeInt hh)+                (Encoding.encodeInt mm)+                (   Encoding.encodeTag 4+                <>  encodeList2+                        (Encoding.encodeInt exponent)+                        encodedMantissa+                )+          where+            exponent = negate (fromIntegral precision)++            mantissa :: Integer+            mantissa = truncate (ss * 10 ^ precision)++            encodedMantissa+                |  fromIntegral (minBound :: Int) <= mantissa+                && mantissa <= fromIntegral (maxBound :: Int) =+                    Encoding.encodeInt (fromInteger mantissa)+                | otherwise =+                    Encoding.encodeInteger mantissa++        TimeZoneLiteral (Time.TimeZone minutes _ _) ->+            encodeList4+                (Encoding.encodeInt 32)+                (Encoding.encodeBool sign)+                (Encoding.encodeInt _HH)+                (Encoding.encodeInt _MM)+          where+            sign = 0 <= minutes++            (_HH, _MM) = abs minutes `divMod` 60++        ShowConstructor t ->+            encodeList2+                (Encoding.encodeInt 34)+                (go t)++        Note _ b ->+            go b++    encodeOperator n l r =+        encodeList4+            (Encoding.encodeInt 3)+            (Encoding.encodeInt n)+            (go l)+            (go r)++    encodeMapWith encodeValue m =+            Encoding.encodeMapLen (fromIntegral (Dhall.Map.size m))+        <>  foldMap encodeKeyValue (Dhall.Map.toList (Dhall.Map.sort m))+      where+        encodeKeyValue (k, v) = Encoding.encodeString k <> encodeValue v++encodeList1 :: Encoding -> Encoding+encodeList1 a = Encoding.encodeListLen 1 <> a+{-# INLINE encodeList1 #-}++encodeList2 :: Encoding -> Encoding -> Encoding+encodeList2 a b = Encoding.encodeListLen 2 <> a <> b+{-# INLINE encodeList2 #-}++encodeList3 :: Encoding -> Encoding -> Encoding -> Encoding+encodeList3 a b c = Encoding.encodeListLen 3 <> a <> b <> c+{-# INLINE encodeList3 #-}++encodeList4 :: Encoding -> Encoding -> Encoding -> Encoding -> Encoding+encodeList4 a b c d = Encoding.encodeListLen 4 <> a <> b <> c <> d+{-# INLINE encodeList4 #-}++encodeListN :: Foldable f => Int -> f Encoding -> Encoding+encodeListN len xs =+    Encoding.encodeListLen (fromIntegral len) <> Foldable.fold xs+{-# INLINE encodeListN #-}++encodeList :: Foldable f => f Encoding -> Encoding+encodeList xs = encodeListN (length xs) xs+{-# INLINE encodeList #-}++decodeImport :: Int -> Decoder s Import+decodeImport len = do+    let die message = fail ("Dhall.Binary.decodeImport: " <> message)++    tokenType₀ <- Decoding.peekTokenType++    hash <- case tokenType₀ of+        TypeNull -> do+            Decoding.decodeNull++            return Nothing++        TypeBytes -> do+            bytes <- Decoding.decodeBytes++            let (prefix, suffix) = Data.ByteString.splitAt 2 bytes++            case prefix of+                "\x12\x20" -> return ()+                _          -> die ("Unrecognized multihash prefix: " <> show prefix)+            case Dhall.Crypto.sha256DigestFromByteString suffix of+                Nothing     -> die ("Invalid sha256 digest: " <> show bytes)+                Just digest -> return (Just digest)++        _ ->+            die ("Unexpected hash token: " <> show tokenType₀)++    m <- Decoding.decodeWord++    importMode <- case m of+        0 -> return Code+        1 -> return RawText+        2 -> return Location+        3 -> return RawBytes+        _ -> die ("Unexpected code for import mode: " <> show m)++    let remote scheme = do+            tokenType₁ <- Decoding.peekTokenType++            headers <- case tokenType₁ of+                TypeNull -> do+                    Decoding.decodeNull+                    return Nothing++                _ -> do+                    headers <- decodeExpressionInternal decodeImport++                    return (Just headers)++            authority <- Decoding.decodeString++            paths <- replicateDecoder (len - 8) Decoding.decodeString++            file <- Decoding.decodeString++            tokenType₂ <- Decoding.peekTokenType++            query <- case tokenType₂ of+                TypeNull -> do+                    Decoding.decodeNull+                    return Nothing+                _ ->+                    fmap Just Decoding.decodeString++            let components = reverse paths+            let directory  = Directory {..}+            let path       = File {..}++            return (Remote (URL {..}))++    let local prefix = do+            paths <- replicateDecoder (len - 5) Decoding.decodeString++            file <- Decoding.decodeString++            let components = reverse paths+            let directory  = Directory {..}++            return (Local prefix (File {..}))++    let missing = return Missing++    let env = do+            x <- Decoding.decodeString++            return (Env x)++    n <- Decoding.decodeWord++    importType <- case n of+        0 -> remote HTTP+        1 -> remote HTTPS+        2 -> local Absolute+        3 -> local Here+        4 -> local Parent+        5 -> local Home+        6 -> env+        7 -> missing+        _ -> fail ("Unrecognized import type code: " <> show n)++    let importHashed = ImportHashed {..}++    return (Import {..})++encodeImport :: Import -> Encoding+encodeImport import_ =+    case importType of+        Remote (URL { scheme = scheme₀, .. }) ->+            encodeList+                (   prefix+                ++  [ Encoding.encodeInt scheme₁+                    , using+                    , Encoding.encodeString authority+                    ]+                ++  map Encoding.encodeString (reverse components)+                ++  [ Encoding.encodeString file ]+                ++  [ case query of+                         Nothing -> Encoding.encodeNull+                         Just q  -> Encoding.encodeString q+                    ]+                )+          where+            using = case headers of+                Nothing ->+                    Encoding.encodeNull+                Just h ->+                    encodeExpressionInternal encodeImport (Syntax.denote h)++            scheme₁ = case scheme₀ of+                HTTP  -> 0+                HTTPS -> 1++            File{..} = path++            Directory {..} = directory++        Local prefix₀ path ->+            encodeList+                (   prefix+                ++  [ Encoding.encodeInt prefix₁ ]+                ++  map Encoding.encodeString components₁+                ++  [ Encoding.encodeString file ]+                )+          where+            File{..} = path++            Directory{..} = directory++            prefix₁ = case prefix₀ of+                Absolute -> 2+                Here     -> 3+                Parent   -> 4+                Home     -> 5++            components₁ = reverse components++        Env x ->+            encodeList+                (prefix ++ [ Encoding.encodeInt 6, Encoding.encodeString x ])++        Missing ->+            encodeList (prefix ++ [ Encoding.encodeInt 7 ])+  where+    prefix = [ Encoding.encodeInt 24, h, m ]+      where+        h = case hash of+            Nothing ->+                Encoding.encodeNull++            Just digest ->+                Encoding.encodeBytes ("\x12\x20" <> Dhall.Crypto.unSHA256Digest digest)++        m = Encoding.encodeInt (case importMode of+            Code -> 0+            RawText -> 1+            Location -> 2+            RawBytes -> 3 )++    Import{..} = import_++    ImportHashed{..} = importHashed++decodeVoid :: Int -> Decoder s Void+decodeVoid _ = fail "Dhall.Binary.decodeVoid: Cannot decode an uninhabited type"++encodeVoid :: Void -> Encoding+encodeVoid = absurd++instance Serialise (Expr Void Void) where+    encode = encodeExpressionInternal encodeVoid++    decode = decodeExpressionInternal decodeVoid++instance Serialise (Expr Void Import) where+    encode = encodeExpressionInternal encodeImport++    decode = decodeExpressionInternal decodeImport++-- | Encode a Dhall expression as a CBOR-encoded `ByteString`+encodeExpression :: Serialise (Expr Void a) => Expr Void a -> ByteString+encodeExpression = Serialise.serialise++-- | Decode a Dhall expression from a CBOR `Codec.CBOR.Term.Term`+decodeExpression+    :: Serialise (Expr s a) => ByteString -> Either DecodingFailure (Expr s a)+decodeExpression bytes =+    case decodeWithoutVersion <|> decodeWithVersion of+        Just expression -> Right expression+        Nothing         -> Left (CBORIsNotDhall bytes)+  where+    adapt (Right ("", x)) = Just x+    adapt  _              = Nothing++    decode' = decodeWith55799Tag decode++    -- This is the behavior specified by the standard+    decodeWithoutVersion = adapt (Read.deserialiseFromBytes decode' bytes)++    -- tag to ease the migration+    decodeWithVersion = adapt (Read.deserialiseFromBytes decodeWithTag bytes)+      where+        decodeWithTag = do+            2 <- Decoding.decodeListLen++            version <- Decoding.decodeString+++            -- "_" has never been a valid version string, and this ensures that+            -- we don't interpret `[ "_", 0 ]` as the expression `_` (encoded as+            -- `0`) tagged with a version string of `"_"`+            if (version == "_")+                then fail "Dhall.Binary.decodeExpression: \"_\" is not a valid version string"+                else return ()++            decode'++decodeWith55799Tag :: Decoder s a -> Decoder s a+decodeWith55799Tag decoder = do+    tokenType <- Decoding.peekTokenType++    case tokenType of+        TypeTag -> do+            w <- Decoding.decodeTag++            if w /= 55799+                then fail ("Dhall.Binary.decodeWith55799Tag: Unexpected tag: " <> show w)+                else return ()++            decoder+        _ ->+            decoder++{-| This indicates that a given CBOR-encoded `ByteString` did not correspond to+    a valid Dhall expression+-}+newtype DecodingFailure = CBORIsNotDhall ByteString+    deriving (Eq)++instance Exception DecodingFailure++_ERROR :: String+_ERROR = "\ESC[1;31mError\ESC[0m"++instance Show DecodingFailure where+    show (CBORIsNotDhall bytes) =+            _ERROR <> ": Cannot decode CBOR to Dhall\n"+        <>  "\n"+        <>  "The following bytes do not encode a valid Dhall expression\n"+        <>  "\n"+        <>  "↳ 0x" <> concatMap toHex (Data.ByteString.Lazy.unpack bytes) <> "\n"+      where+        toHex = Printf.printf "%02x "++-- | This specialized version of 'Control.Monad.replicateM' reduces+-- decoding timings by roughly 10%.+replicateDecoder :: Int -> Decoder s a -> Decoder s [a]+replicateDecoder n0 decoder = go n0+  where+    go n+      | n <= 0    = pure []+      | otherwise = do+            x <- decoder+            xs <- go (n - 1)+            pure (x:xs)
− src/Dhall/Binary.hs-boot
@@ -1,10 +0,0 @@-module Dhall.Binary where--import Codec.CBOR.Term (Term)--import {-# SOURCE #-} Dhall.Core--class ToTerm a where-    encode :: a -> Term--instance ToTerm a => ToTerm (Expr s a)
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)@ @@ -57,7 +57,7 @@ > lookup k n (insert k v c) = lookup k (n - 1) c > lookup k n (insert j v c) = lookup k  n      c  -- k /= j -}-lookup :: Text -> Integer -> Context a -> Maybe a+lookup :: Text -> Int -> Context a -> Maybe a lookup _ _ (Context         []  ) =     Nothing lookup x n (Context ((k, v):kvs)) =
src/Dhall/Core.hs view
@@ -1,2147 +1,156 @@-{-# LANGUAGE BangPatterns       #-}-{-# LANGUAGE CPP                #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric      #-}-{-# LANGUAGE DeriveTraversable  #-}-{-# LANGUAGE OverloadedStrings  #-}-{-# LANGUAGE RankNTypes         #-}-{-# LANGUAGE RecordWildCards    #-}-{-# LANGUAGE UnicodeSyntax      #-}-{-# OPTIONS_GHC -Wall #-}--{-| This module contains the core calculus for the Dhall language.--    Dhall is essentially a fork of the @morte@ compiler but with more built-in-    functionality, better error messages, and Haskell integration--}--module Dhall.Core (-    -- * Syntax-      Const(..)-    , Directory(..)-    , File(..)-    , FilePrefix(..)-    , Import(..)-    , ImportHashed(..)-    , ImportMode(..)-    , ImportType(..)-    , URL(..)-    , Scheme(..)-    , Var(..)-    , Binding(..)-    , Chunks(..)-    , Expr(..)--    -- * Normalization-    , Dhall.Core.alphaNormalize-    , normalize-    , normalizeWith-    , normalizeWithM-    , Normalizer-    , NormalizerM-    , ReifiedNormalizer (..)-    , judgmentallyEqual-    , subst-    , shift-    , isNormalized-    , isNormalizedWith-    , denote-    , freeIn--    -- * Pretty-printing-    , pretty--    -- * Optics-    , subExpressions-    , chunkExprs--    -- * Miscellaneous-    , internalError-    , reservedIdentifiers-    , escapeText-    , pathCharacter-    , throws-    ) where--#if MIN_VERSION_base(4,8,0)-#else-import Control.Applicative (Applicative(..), (<$>))-#endif-import Control.Applicative (empty)-import Control.Exception (Exception)-import Control.Monad.IO.Class (MonadIO(..))-import Crypto.Hash (SHA256)-import Data.Bifunctor (Bifunctor(..))-import Data.Data (Data)-import Data.Foldable-import Data.Functor.Identity (Identity(..))-import Data.HashSet (HashSet)-import Data.List.NonEmpty (NonEmpty(..))-import Data.String (IsString(..))-import Data.Semigroup (Semigroup(..))-import Data.Sequence (Seq, ViewL(..), ViewR(..))-import Data.Text (Text)-import Data.Text.Prettyprint.Doc (Doc, Pretty)-import Data.Traversable-import Dhall.Map (Map)-import Dhall.Set (Set)-import Dhall.Src (Src)-import {-# SOURCE #-} Dhall.Pretty.Internal-import GHC.Generics (Generic)-import Numeric.Natural (Natural)-import Prelude hiding (succ)--import qualified Control.Exception-import qualified Control.Monad-import qualified Crypto.Hash-import qualified Data.Char-import {-# SOURCE #-} qualified Dhall.Eval-import qualified Data.HashSet-import qualified Data.Sequence-import qualified Data.Text-import qualified Data.Text.Prettyprint.Doc  as Pretty-import qualified Dhall.Map-import qualified Dhall.Set-import qualified Network.URI.Encode         as URI.Encode-import qualified Text.Printf---{-| 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)--instance Pretty Const where-    pretty = Pretty.unAnnotate . prettyConst--{-| 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)--instance Semigroup Directory where-    Directory components₀ <> Directory components₁ =-        Directory (components₁ <> components₀)--instance Pretty Directory where-    pretty (Directory {..}) = foldMap prettyPathComponent (reverse components)--{-| 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)--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)--instance Pretty FilePrefix where-    pretty Absolute = ""-    pretty Here     = "."-    pretty Parent   = ".."-    pretty Home     = "~"--data Scheme = HTTP | HTTPS deriving (Eq, Generic, Ord, Show)--data URL = URL-    { scheme    :: Scheme-    , authority :: Text-    , path      :: File-    , query     :: Maybe Text-    , headers   :: Maybe (Expr Src Import)-    } deriving (Eq, Generic, Ord, Show)--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---- | 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)--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:" <> Pretty.pretty env--    pretty Missing = "missing"---- | How to interpret the import's contents (i.e. as Dhall code or raw text)-data ImportMode = Code | RawText deriving (Eq, Generic, Ord, Show)---- | A `ImportType` extended with an optional hash for semantic integrity checks-data ImportHashed = ImportHashed-    { hash       :: Maybe (Crypto.Hash.Digest SHA256)-    , importType :: ImportType-    } deriving (Eq, Generic, Ord, Show)--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)--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"-            Code    -> ""--{-| Label for a bound variable--    The `Text` field is the variable's name (i.e. \"@x@\").--    The `Int` field disambiguates variables with the same name if there are-    multiple bound variables of the same name in scope.  Zero refers to the-    nearest bound variable and the index increases by one for each bound-    variable of the same name going outward.  The following diagram may help:-->                               ┌──refers to──┐->                               │             │->                               v             │-> λ(x : Type) → λ(y : Type) → λ(x : Type) → x@0->-> ┌─────────────────refers to─────────────────┐-> │                                           │-> v                                           │-> λ(x : Type) → λ(y : Type) → λ(x : Type) → x@1--    This `Int` behaves like a De Bruijn index in the special case where all-    variables have the same name.--    You can optionally omit the index if it is @0@:-->                               ┌─refers to─┐->                               │           │->                               v           │-> λ(x : Type) → λ(y : Type) → λ(x : Type) → x--    Zero indices are omitted when pretty-printing `Var`s and non-zero indices-    appear as a numeric suffix.--}-data Var = V Text !Integer-    deriving (Data, Generic, Eq, Ord, Show)--instance IsString Var where-    fromString str = V (fromString str) 0--instance Pretty Var where-    pretty = Pretty.unAnnotate . prettyVar---- | Syntax tree for expressions-data Expr s a-    -- | > Const c                                  ~  c-    = Const Const-    -- | > Var (V x 0)                              ~  x-    --   > Var (V x n)                              ~  x@n-    | Var Var-    -- | > Lam x     A b                            ~  λ(x : A) -> b-    | Lam Text (Expr s a) (Expr s a)-    -- | > Pi "_" A B                               ~        A  -> B-    --   > Pi x   A B                               ~  ∀(x : A) -> B-    | Pi  Text (Expr s a) (Expr s a)-    -- | > App f a                                  ~  f a-    | App (Expr s a) (Expr s a)-    -- | > Let [Binding x Nothing  r] e             ~  let x     = r in e-    --   > Let [Binding x (Just t) r] e             ~  let x : t = r in e-    | Let (NonEmpty (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-    -- | > NaturalPlus x y                          ~  x + y-    | NaturalPlus (Expr s a) (Expr s a)-    -- | > NaturalTimes x y                         ~  x * y-    | NaturalTimes (Expr s a) (Expr s a)-    -- | > Integer                                  ~  Integer-    | Integer-    -- | > IntegerLit n                             ~  ±n-    | IntegerLit Integer-    -- | > IntegerShow                              ~  Integer/show-    | IntegerShow-    -- | > IntegerToDouble                          ~  Integer/toDouble-    | IntegerToDouble-    -- | > Double                                   ~  Double-    | Double-    -- | > DoubleLit n                              ~  n-    | DoubleLit Double-    -- | > 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 ) [x, y, z]              ~  [x, y, z] : List t-    --   > ListLit  Nothing  [x, y, z]              ~  [x, y, z]-    | ListLit (Maybe (Expr s a)) (Seq (Expr s a))-    -- | > ListAppend x y                           ~  x # y-    | ListAppend (Expr s a) (Expr s a)-    -- | > ListBuild                                ~  List/build-    | ListBuild-    -- | > ListFold                                 ~  List/fold-    | ListFold-    -- | > ListLength                               ~  List/length-    | ListLength-    -- | > ListHead                                 ~  List/head-    | ListHead-    -- | > ListLast                                 ~  List/last-    | ListLast-    -- | > ListIndexed                              ~  List/indexed-    | ListIndexed-    -- | > ListReverse                              ~  List/reverse-    | ListReverse-    -- | > Optional                                 ~  Optional-    | Optional-    -- | > OptionalLit t (Just e)                   ~  [e] : Optional t-    --   > OptionalLit t Nothing                    ~  []  : Optional t-    | OptionalLit (Expr s a) (Maybe (Expr s a))-    -- | > 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)))-    -- | > UnionLit k v [(k1, Just t1), (k2, Nothing)] ~  < k = v | k1 : t1 | k2 >-    | UnionLit Text (Expr s a) (Map Text (Maybe (Expr s a)))-    -- | > Combine x y                              ~  x ∧ y-    | Combine (Expr s a) (Expr s a)-    -- | > CombineTypes x y                         ~  x ⩓ y-    | CombineTypes (Expr s a) (Expr s a)-    -- | > Prefer x y                               ~  x ⫽ y-    | Prefer (Expr s a) (Expr s a)-    -- | > Merge x y (Just t )                      ~  merge x y : t-    --   > Merge x y  Nothing                       ~  merge x y-    | Merge (Expr s a) (Expr s a) (Maybe (Expr s a))-    -- | > 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))-    -- | > 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 (Eq, Ord, Foldable, Generic, Traversable, Show, Data)---- 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 _ (Const c) = Const c-  fmap _ (Var v) = Var v-  fmap f (Lam v e1 e2) = Lam v (fmap f e1) (fmap f e2)-  fmap f (Pi v e1 e2) = Pi v (fmap f e1) (fmap f e2)-  fmap f (App e1 e2) = App (fmap f e1) (fmap f e2)-  fmap f (Let as b) = Let (fmap (fmap f) as) (fmap f b)-  fmap f (Annot e1 e2) = Annot (fmap f e1) (fmap f e2)-  fmap _ Bool = Bool-  fmap _ (BoolLit b) = BoolLit b-  fmap f (BoolAnd e1 e2) = BoolAnd (fmap f e1) (fmap f e2)-  fmap f (BoolOr e1 e2) = BoolOr (fmap f e1) (fmap f e2)-  fmap f (BoolEQ e1 e2) = BoolEQ (fmap f e1) (fmap f e2)-  fmap f (BoolNE e1 e2) = BoolNE (fmap f e1) (fmap f e2)-  fmap f (BoolIf e1 e2 e3) = BoolIf (fmap f e1) (fmap f e2) (fmap f e3)-  fmap _ Natural = Natural-  fmap _ (NaturalLit n) = NaturalLit n-  fmap _ NaturalFold = NaturalFold-  fmap _ NaturalBuild = NaturalBuild-  fmap _ NaturalIsZero = NaturalIsZero-  fmap _ NaturalEven = NaturalEven-  fmap _ NaturalOdd = NaturalOdd-  fmap _ NaturalToInteger = NaturalToInteger-  fmap _ NaturalShow = NaturalShow-  fmap f (NaturalPlus e1 e2) = NaturalPlus (fmap f e1) (fmap f e2)-  fmap f (NaturalTimes e1 e2) = NaturalTimes (fmap f e1) (fmap f e2)-  fmap _ Integer = Integer-  fmap _ (IntegerLit i) = IntegerLit i-  fmap _ IntegerShow = IntegerShow-  fmap _ IntegerToDouble = IntegerToDouble-  fmap _ Double = Double-  fmap _ (DoubleLit d) = DoubleLit d-  fmap _ DoubleShow = DoubleShow-  fmap _ Text = Text-  fmap f (TextLit cs) = TextLit (fmap f cs)-  fmap f (TextAppend e1 e2) = TextAppend (fmap f e1) (fmap f e2)-  fmap _ TextShow = TextShow-  fmap _ List = List-  fmap f (ListLit maybeE seqE) = ListLit (fmap (fmap f) maybeE) (fmap (fmap f) seqE)-  fmap f (ListAppend e1 e2) = ListAppend (fmap f e1) (fmap f e2)-  fmap _ ListBuild = ListBuild-  fmap _ ListFold = ListFold-  fmap _ ListLength = ListLength-  fmap _ ListHead = ListHead-  fmap _ ListLast = ListLast-  fmap _ ListIndexed = ListIndexed-  fmap _ ListReverse = ListReverse-  fmap _ Optional = Optional-  fmap f (OptionalLit e maybeE) = OptionalLit (fmap f e) (fmap (fmap f) maybeE)-  fmap f (Some e) = Some (fmap f e)-  fmap _ None = None-  fmap _ OptionalFold = OptionalFold-  fmap _ OptionalBuild = OptionalBuild-  fmap f (Record r) = Record (fmap (fmap f) r)-  fmap f (RecordLit r) = RecordLit (fmap (fmap f) r)-  fmap f (Union u) = Union (fmap (fmap (fmap f)) u)-  fmap f (UnionLit v e u) = UnionLit v (fmap f e) (fmap (fmap (fmap f)) u)-  fmap f (Combine e1 e2) = Combine (fmap f e1) (fmap f e2)-  fmap f (CombineTypes e1 e2) = CombineTypes (fmap f e1) (fmap f e2)-  fmap f (Prefer e1 e2) = Prefer (fmap f e1) (fmap f e2)-  fmap f (Merge e1 e2 maybeE) = Merge (fmap f e1) (fmap f e2) (fmap (fmap f) maybeE)-  fmap f (Field e1 v) = Field (fmap f e1) v-  fmap f (Project e1 vs) = Project (fmap f e1) (fmap (fmap f) vs)-  fmap f (Note s e1) = Note s (fmap f e1)-  fmap f (ImportAlt e1 e2) = ImportAlt (fmap f e1) (fmap f e2)-  fmap f (Embed a) = Embed (f a)-  {-# INLINABLE fmap #-}--instance Applicative (Expr s) where-    pure = Embed--    (<*>) = Control.Monad.ap--instance Monad (Expr s) where-    return = pure--    Const a              >>= _ = Const a-    Var a                >>= _ = Var a-    Lam a b c            >>= k = Lam a (b >>= k) (c >>= k)-    Pi  a b c            >>= k = Pi a (b >>= k) (c >>= k)-    App a b              >>= k = App (a >>= k) (b >>= k)-    Let as b             >>= k = Let (fmap f as) (b >>= k)-      where-        f (Binding c d e) = Binding c (fmap (>>= k) d) (e >>= k)-    Annot a b            >>= k = Annot (a >>= k) (b >>= k)-    Bool                 >>= _ = Bool-    BoolLit a            >>= _ = BoolLit a-    BoolAnd a b          >>= k = BoolAnd (a >>= k) (b >>= k)-    BoolOr  a b          >>= k = BoolOr  (a >>= k) (b >>= k)-    BoolEQ  a b          >>= k = BoolEQ  (a >>= k) (b >>= k)-    BoolNE  a b          >>= k = BoolNE  (a >>= k) (b >>= k)-    BoolIf a b c         >>= k = BoolIf (a >>= k) (b >>= k) (c >>= k)-    Natural              >>= _ = Natural-    NaturalLit a         >>= _ = NaturalLit a-    NaturalFold          >>= _ = NaturalFold-    NaturalBuild         >>= _ = NaturalBuild-    NaturalIsZero        >>= _ = NaturalIsZero-    NaturalEven          >>= _ = NaturalEven-    NaturalOdd           >>= _ = NaturalOdd-    NaturalToInteger     >>= _ = NaturalToInteger-    NaturalShow          >>= _ = NaturalShow-    NaturalPlus  a b     >>= k = NaturalPlus  (a >>= k) (b >>= k)-    NaturalTimes a b     >>= k = NaturalTimes (a >>= k) (b >>= k)-    Integer              >>= _ = Integer-    IntegerLit a         >>= _ = IntegerLit a-    IntegerShow          >>= _ = IntegerShow-    IntegerToDouble      >>= _ = IntegerToDouble-    Double               >>= _ = Double-    DoubleLit a          >>= _ = DoubleLit a-    DoubleShow           >>= _ = DoubleShow-    Text                 >>= _ = Text-    TextLit (Chunks a b) >>= k = TextLit (Chunks (fmap (fmap (>>= k)) a) b)-    TextAppend a b       >>= k = TextAppend (a >>= k) (b >>= k)-    TextShow             >>= _ = TextShow-    List                 >>= _ = List-    ListLit a b          >>= k = ListLit (fmap (>>= k) a) (fmap (>>= k) b)-    ListAppend a b       >>= k = ListAppend (a >>= k) (b >>= k)-    ListBuild            >>= _ = ListBuild-    ListFold             >>= _ = ListFold-    ListLength           >>= _ = ListLength-    ListHead             >>= _ = ListHead-    ListLast             >>= _ = ListLast-    ListIndexed          >>= _ = ListIndexed-    ListReverse          >>= _ = ListReverse-    Optional             >>= _ = Optional-    OptionalLit a b      >>= k = OptionalLit (a >>= k) (fmap (>>= k) b)-    Some a               >>= k = Some (a >>= k)-    None                 >>= _ = None-    OptionalFold         >>= _ = OptionalFold-    OptionalBuild        >>= _ = OptionalBuild-    Record    a          >>= k = Record (fmap (>>= k) a)-    RecordLit a          >>= k = RecordLit (fmap (>>= k) a)-    Union     a          >>= k = Union (fmap (fmap (>>= k)) a)-    UnionLit a b c       >>= k = UnionLit a (b >>= k) (fmap (fmap (>>= k)) c)-    Combine a b          >>= k = Combine (a >>= k) (b >>= k)-    CombineTypes a b     >>= k = CombineTypes (a >>= k) (b >>= k)-    Prefer a b           >>= k = Prefer (a >>= k) (b >>= k)-    Merge a b c          >>= k = Merge (a >>= k) (b >>= k) (fmap (>>= k) c)-    Field a b            >>= k = Field (a >>= k) b-    Project a b          >>= k = Project (a >>= k) (fmap (>>= k) b)-    Note a b             >>= k = Note a (b >>= k)-    ImportAlt a b        >>= k = ImportAlt (a >>= k) (b >>= k)-    Embed a              >>= k = k a--instance Bifunctor Expr where-    first _ (Const a             ) = Const a-    first _ (Var a               ) = Var a-    first k (Lam a b c           ) = Lam a (first k b) (first k c)-    first k (Pi a b c            ) = Pi a (first k b) (first k c)-    first k (App a b             ) = App (first k a) (first k b)-    first k (Let as b            ) = Let (fmap (first k) as) (first k b)-    first k (Annot a b           ) = Annot (first k a) (first k b)-    first _  Bool                  = Bool-    first _ (BoolLit a           ) = BoolLit a-    first k (BoolAnd a b         ) = BoolAnd (first k a) (first k b)-    first k (BoolOr a b          ) = BoolOr (first k a) (first k b)-    first k (BoolEQ a b          ) = BoolEQ (first k a) (first k b)-    first k (BoolNE a b          ) = BoolNE (first k a) (first k b)-    first k (BoolIf a b c        ) = BoolIf (first k a) (first k b) (first k c)-    first _  Natural               = Natural-    first _ (NaturalLit a        ) = NaturalLit a-    first _  NaturalFold           = NaturalFold-    first _  NaturalBuild          = NaturalBuild-    first _  NaturalIsZero         = NaturalIsZero-    first _  NaturalEven           = NaturalEven-    first _  NaturalOdd            = NaturalOdd-    first _  NaturalToInteger      = NaturalToInteger-    first _  NaturalShow           = NaturalShow-    first k (NaturalPlus a b     ) = NaturalPlus (first k a) (first k b)-    first k (NaturalTimes a b    ) = NaturalTimes (first k a) (first k b)-    first _  Integer               = Integer-    first _ (IntegerLit a        ) = IntegerLit a-    first _  IntegerShow           = IntegerShow-    first _  IntegerToDouble       = IntegerToDouble-    first _  Double                = Double-    first _ (DoubleLit a         ) = DoubleLit a-    first _  DoubleShow            = DoubleShow-    first _  Text                  = Text-    first k (TextLit (Chunks a b)) = TextLit (Chunks (fmap (fmap (first k)) a) b)-    first k (TextAppend a b      ) = TextAppend (first k a) (first k b)-    first _  TextShow              = TextShow-    first _  List                  = List-    first k (ListLit a b         ) = ListLit (fmap (first k) a) (fmap (first k) b)-    first k (ListAppend a b      ) = ListAppend (first k a) (first k b)-    first _  ListBuild             = ListBuild-    first _  ListFold              = ListFold-    first _  ListLength            = ListLength-    first _  ListHead              = ListHead-    first _  ListLast              = ListLast-    first _  ListIndexed           = ListIndexed-    first _  ListReverse           = ListReverse-    first _  Optional              = Optional-    first k (OptionalLit a b     ) = OptionalLit (first k a) (fmap (first k) b)-    first k (Some a              ) = Some (first k a)-    first _  None                  = None-    first _  OptionalFold          = OptionalFold-    first _  OptionalBuild         = OptionalBuild-    first k (Record a            ) = Record (fmap (first k) a)-    first k (RecordLit a         ) = RecordLit (fmap (first k) a)-    first k (Union a             ) = Union (fmap (fmap (first k)) a)-    first k (UnionLit a b c      ) = UnionLit a (first k b) (fmap (fmap (first k)) c)-    first k (Combine a b         ) = Combine (first k a) (first k b)-    first k (CombineTypes a b    ) = CombineTypes (first k a) (first k b)-    first k (Prefer a b          ) = Prefer (first k a) (first k b)-    first k (Merge a b c         ) = Merge (first k a) (first k b) (fmap (first k) c)-    first k (Field a b           ) = Field (first k a) b-    first k (Project a b         ) = Project (first k a) (fmap (first k) b)-    first k (Note a b            ) = Note (k a) (first k b)-    first k (ImportAlt a b       ) = ImportAlt (first k a) (first k b)-    first _ (Embed a             ) = Embed a--    second = fmap--instance IsString (Expr s a) where-    fromString str = Var (fromString str)--data Binding s a = Binding-    { variable   :: Text-    , annotation :: Maybe (Expr s a)-    , value      :: Expr s a-    } deriving (Functor, Foldable, Generic, Traversable, Show, Eq, Ord, Data)--instance Bifunctor Binding where-    first k (Binding a b c) = Binding a (fmap (first k) b) (first k c)--    second = fmap---- | 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)--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)--{-  There is a one-to-one correspondence between the builders in this section-    and the sub-parsers in "Dhall.Parser".  Each builder is named after the-    corresponding parser and the relationship between builders exactly matches-    the relationship between parsers.  This leads to the nice emergent property-    of automatically getting all the parentheses and precedences right.--    This approach has one major disadvantage: you can get an infinite loop if-    you add a new constructor to the syntax tree without adding a matching-    case the corresponding builder.--}---- | Generates a syntactically valid Dhall program-instance Pretty a => Pretty (Expr s a) where-    pretty = Pretty.unAnnotate . prettyExpr--{-| `shift` is used by both normalization and type-checking to avoid variable-    capture by shifting variable indices--    For example, suppose that you were to normalize the following expression:--> λ(a : Type) → λ(x : a) → (λ(y : a) → λ(x : a) → y) x--    If you were to substitute @y@ with @x@ without shifting any variable-    indices, then you would get the following incorrect result:--> λ(a : Type) → λ(x : a) → λ(x : a) → x  -- Incorrect normalized form--    In order to substitute @x@ in place of @y@ we need to `shift` @x@ by @1@ in-    order to avoid being misinterpreted as the @x@ bound by the innermost-    lambda.  If we perform that `shift` then we get the correct result:--> λ(a : Type) → λ(x : a) → λ(x : a) → x@1--    As a more worked example, suppose that you were to normalize the following-    expression:-->     λ(a : Type)-> →   λ(f : a → a → a)-> →   λ(x : a)-> →   λ(x : a)-> →   (λ(x : a) → f x x@1) x@1--    The correct normalized result would be:-->     λ(a : Type)-> →   λ(f : a → a → a)-> →   λ(x : a)-> →   λ(x : a)-> →   f x@1 x--    The above example illustrates how we need to both increase and decrease-    variable indices as part of substitution:--    * We need to increase the index of the outer @x\@1@ to @x\@2@ before we-      substitute it into the body of the innermost lambda expression in order-      to avoid variable capture.  This substitution changes the body of the-      lambda expression to @(f x\@2 x\@1)@--    * We then remove the innermost lambda and therefore decrease the indices of-      both @x@s in @(f x\@2 x\@1)@ to @(f x\@1 x)@ in order to reflect that one-      less @x@ variable is now bound within that scope--    Formally, @(shift d (V x n) e)@ modifies the expression @e@ by adding @d@ to-    the indices of all variables named @x@ whose indices are greater than-    @(n + m)@, where @m@ is the number of bound variables of the same name-    within that scope--    In practice, @d@ is always @1@ or @-1@ because we either:--    * increment variables by @1@ to avoid variable capture during substitution-    * decrement variables by @1@ when deleting lambdas after substitution--    @n@ starts off at @0@ when substitution begins and increments every time we-    descend into a lambda or let expression that binds a variable of the same-    name in order to avoid shifting the bound variables by mistake.--}-shift :: Integer -> Var -> Expr s a -> Expr s a-shift _ _ (Const a) = Const a-shift d (V x n) (Var (V x' n')) = Var (V x' n'')-  where-    n'' = if x == x' && n <= n' then n' + d else n'-shift d (V x n) (Lam x' _A b) = Lam x' _A' b'-  where-    _A' = shift d (V x n ) _A-    b'  = shift d (V x n') b-      where-        n' = if x == x' then n + 1 else n-shift d (V x n) (Pi x' _A _B) = Pi x' _A' _B'-  where-    _A' = shift d (V x n ) _A-    _B' = shift d (V x n') _B-      where-        n' = if x == x' then n + 1 else n-shift d v (App f a) = App f' a'-  where-    f' = shift d v f-    a' = shift d v a-shift d (V x₀ n₀) (Let (Binding x₁ mA₀ a₀ :| []) b₀) =-    Let (Binding x₁ mA₁ a₁ :| []) b₁-  where-    n₁ = if x₀ == x₁ then n₀ + 1 else n₀--    mA₁ = fmap (shift d (V x₀ n₀)) mA₀-    a₁  =       shift d (V x₀ n₀)   a₀--    b₁  =       shift d (V x₀ n₁)   b₀-shift d (V x₀ n₀) (Let (Binding x₁ mA₀ a₀ :| (l₀ : ls₀)) b₀) =-    case shift d (V x₀ n₁) (Let (l₀ :| ls₀) b₀) of-        Let (l₁ :| ls₁) b₁ -> Let (Binding x₁ mA₁ a₁ :| (l₁ : ls₁)) b₁-        e                  -> Let (Binding x₁ mA₁ a₁ :|       []  ) e-  where-    n₁ = if x₀ == x₁ then n₀ + 1 else n₀--    mA₁ = fmap (shift d (V x₀ n₀)) mA₀-    a₁  =       shift d (V x₀ n₀)   a₀--shift d v (Annot a b) = Annot a' b'-  where-    a' = shift d v a-    b' = shift d v b-shift _ _ Bool = Bool-shift _ _ (BoolLit a) = BoolLit a-shift d v (BoolAnd a b) = BoolAnd a' b'-  where-    a' = shift d v a-    b' = shift d v b-shift d v (BoolOr a b) = BoolOr a' b'-  where-    a' = shift d v a-    b' = shift d v b-shift d v (BoolEQ a b) = BoolEQ a' b'-  where-    a' = shift d v a-    b' = shift d v b-shift d v (BoolNE a b) = BoolNE a' b'-  where-    a' = shift d v a-    b' = shift d v b-shift d v (BoolIf a b c) = BoolIf a' b' c'-  where-    a' = shift d v a-    b' = shift d v b-    c' = shift d v c-shift _ _ Natural = Natural-shift _ _ (NaturalLit a) = NaturalLit a-shift _ _ NaturalFold = NaturalFold-shift _ _ NaturalBuild = NaturalBuild-shift _ _ NaturalIsZero = NaturalIsZero-shift _ _ NaturalEven = NaturalEven-shift _ _ NaturalOdd = NaturalOdd-shift _ _ NaturalToInteger = NaturalToInteger-shift _ _ NaturalShow = NaturalShow-shift d v (NaturalPlus a b) = NaturalPlus a' b'-  where-    a' = shift d v a-    b' = shift d v b-shift d v (NaturalTimes a b) = NaturalTimes a' b'-  where-    a' = shift d v a-    b' = shift d v b-shift _ _ Integer = Integer-shift _ _ (IntegerLit a) = IntegerLit a-shift _ _ IntegerShow = IntegerShow-shift _ _ IntegerToDouble = IntegerToDouble-shift _ _ Double = Double-shift _ _ (DoubleLit a) = DoubleLit a-shift _ _ DoubleShow = DoubleShow-shift _ _ Text = Text-shift d v (TextLit (Chunks a b)) = TextLit (Chunks a' b)-  where-    a' = fmap (fmap (shift d v)) a-shift d v (TextAppend a b) = TextAppend a' b'-  where-    a' = shift d v a-    b' = shift d v b-shift _ _ TextShow = TextShow-shift _ _ List = List-shift d v (ListLit a b) = ListLit a' b'-  where-    a' = fmap (shift d v) a-    b' = fmap (shift d v) b-shift _ _ ListBuild = ListBuild-shift d v (ListAppend a b) = ListAppend a' b'-  where-    a' = shift d v a-    b' = shift d v b-shift _ _ ListFold = ListFold-shift _ _ ListLength = ListLength-shift _ _ ListHead = ListHead-shift _ _ ListLast = ListLast-shift _ _ ListIndexed = ListIndexed-shift _ _ ListReverse = ListReverse-shift _ _ Optional = Optional-shift d v (OptionalLit a b) = OptionalLit a' b'-  where-    a' =       shift d v  a-    b' = fmap (shift d v) b-shift d v (Some a) = Some a'-  where-    a' = shift d v a-shift _ _ None = None-shift _ _ OptionalFold = OptionalFold-shift _ _ OptionalBuild = OptionalBuild-shift d v (Record a) = Record a'-  where-    a' = fmap (shift d v) a-shift d v (RecordLit a) = RecordLit a'-  where-    a' = fmap (shift d v) a-shift d v (Union a) = Union a'-  where-    a' = fmap (fmap (shift d v)) a-shift d v (UnionLit a b c) = UnionLit a b' c'-  where-    b' =             shift d v   b-    c' = fmap (fmap (shift d v)) c-shift d v (Combine a b) = Combine a' b'-  where-    a' = shift d v a-    b' = shift d v b-shift d v (CombineTypes a b) = CombineTypes a' b'-  where-    a' = shift d v a-    b' = shift d v b-shift d v (Prefer a b) = Prefer a' b'-  where-    a' = shift d v a-    b' = shift d v b-shift d v (Merge a b c) = Merge a' b' c'-  where-    a' =       shift d v  a-    b' =       shift d v  b-    c' = fmap (shift d v) c-shift d v (Field a b) = Field a' b-  where-    a' = shift d v a-shift d v (Project a b) = Project a' b-  where-    a' = shift d v a-shift d v (Note a b) = Note a b'-  where-    b' = shift d v b-shift d v (ImportAlt a b) = ImportAlt a' b'-  where-    a' = shift d v a-    b' = shift d v b--- The Dhall compiler enforces that all embedded values are closed expressions--- and `shift` does nothing to a closed expression-shift _ _ (Embed p) = Embed p--{-| Substitute all occurrences of a variable with an expression--> subst x C B  ~  B[x := C]--}-subst :: Var -> Expr s a -> Expr s a -> Expr s a-subst _ _ (Const a) = Const a-subst (V x n) e (Lam y _A b) = Lam y _A' b'-  where-    _A' = subst (V x n )                  e  _A-    b'  = subst (V x n') (shift 1 (V y 0) e)  b-    n'  = if x == y then n + 1 else n-subst (V x n) e (Pi y _A _B) = Pi y _A' _B'-  where-    _A' = subst (V x n )                  e  _A-    _B' = subst (V x n') (shift 1 (V y 0) e) _B-    n'  = if x == y then n + 1 else n-subst v e (App f a) = App f' a'-  where-    f' = subst v e f-    a' = subst v e a-subst v e (Var v') = if v == v' then e else Var v'-subst (V x₀ n₀) e₀ (Let (Binding x₁ mA₀ a₀ :| []) b₀) =-    Let (Binding x₁ mA₁ a₁ :| []) b₁-  where-    n₁ = if x₀ == x₁ then n₀ + 1 else n₀--    e₁ = shift 1 (V x₁ 0) e₀--    mA₁ = fmap (subst (V x₀ n₀) e₀) mA₀-    a₁  =       subst (V x₀ n₀) e₀   a₀--    b₁  =       subst (V x₀ n₁) e₁   b₀-subst (V x₀ n₀) e₀ (Let (Binding x₁ mA₀ a₀ :| (l₀ : ls₀)) b₀) =-    case subst (V x₀ n₁) e₁ (Let (l₀ :| ls₀) b₀) of-        Let (l₁ :| ls₁) b₁ -> Let (Binding x₁ mA₁ a₁ :| (l₁ : ls₁)) b₁-        e                  -> Let (Binding x₁ mA₁ a₁ :|       []  ) e-  where-    n₁ = if x₀ == x₁ then n₀ + 1 else n₀--    e₁ = shift 1 (V x₁ 0) e₀--    mA₁ = fmap (subst (V x₀ n₀) e₀) mA₀-    a₁  =       subst (V x₀ n₀) e₀   a₀--subst x e (Annot a b) = Annot a' b'-  where-    a' = subst x e a-    b' = subst x e b-subst _ _ Bool = Bool-subst _ _ (BoolLit a) = BoolLit a-subst x e (BoolAnd a b) = BoolAnd a' b'-  where-    a' = subst x e a-    b' = subst x e b-subst x e (BoolOr a b) = BoolOr a' b'-  where-    a' = subst x e a-    b' = subst x e b-subst x e (BoolEQ a b) = BoolEQ a' b'-  where-    a' = subst x e a-    b' = subst x e b-subst x e (BoolNE a b) = BoolNE a' b'-  where-    a' = subst x e a-    b' = subst x e b-subst x e (BoolIf a b c) = BoolIf a' b' c'-  where-    a' = subst x e a-    b' = subst x e b-    c' = subst x e c-subst _ _ Natural = Natural-subst _ _ (NaturalLit a) = NaturalLit a-subst _ _ NaturalFold = NaturalFold-subst _ _ NaturalBuild = NaturalBuild-subst _ _ NaturalIsZero = NaturalIsZero-subst _ _ NaturalEven = NaturalEven-subst _ _ NaturalOdd = NaturalOdd-subst _ _ NaturalToInteger = NaturalToInteger-subst _ _ NaturalShow = NaturalShow-subst x e (NaturalPlus a b) = NaturalPlus a' b'-  where-    a' = subst x e a-    b' = subst x e b-subst x e (NaturalTimes a b) = NaturalTimes a' b'-  where-    a' = subst x e a-    b' = subst x e b-subst _ _ Integer = Integer-subst _ _ (IntegerLit a) = IntegerLit a-subst _ _ IntegerShow = IntegerShow-subst _ _ IntegerToDouble = IntegerToDouble-subst _ _ Double = Double-subst _ _ (DoubleLit a) = DoubleLit a-subst _ _ DoubleShow = DoubleShow-subst _ _ Text = Text-subst x e (TextLit (Chunks a b)) = TextLit (Chunks a' b)-  where-    a' = fmap (fmap (subst x e)) a-subst x e (TextAppend a b) = TextAppend a' b'-  where-    a' = subst x e a-    b' = subst x e b-subst _ _ TextShow = TextShow-subst _ _ List = List-subst x e (ListLit a b) = ListLit a' b'-  where-    a' = fmap (subst x e) a-    b' = fmap (subst x e) b-subst x e (ListAppend a b) = ListAppend a' b'-  where-    a' = subst x e a-    b' = subst x e b-subst _ _ ListBuild = ListBuild-subst _ _ ListFold = ListFold-subst _ _ ListLength = ListLength-subst _ _ ListHead = ListHead-subst _ _ ListLast = ListLast-subst _ _ ListIndexed = ListIndexed-subst _ _ ListReverse = ListReverse-subst _ _ Optional = Optional-subst x e (OptionalLit a b) = OptionalLit a' b'-  where-    a' =       subst x e  a-    b' = fmap (subst x e) b-subst x e (Some a) = Some a'-  where-    a' = subst x e a-subst _ _ None = None-subst _ _ OptionalFold = OptionalFold-subst _ _ OptionalBuild = OptionalBuild-subst x e (Record kts) = Record kts'-  where-    kts' = fmap (subst x e) kts-subst x e (RecordLit kvs) = RecordLit kvs'-  where-    kvs' = fmap (subst x e) kvs-subst x e (Union kts) = Union kts'-  where-    kts' = fmap (fmap (subst x e)) kts-subst x e (UnionLit a b kts) = UnionLit a b' kts'-  where-    b'   =             subst x e   b-    kts' = fmap (fmap (subst x e)) kts-subst x e (Combine a b) = Combine a' b'-  where-    a' = subst x e a-    b' = subst x e b-subst x e (CombineTypes a b) = CombineTypes a' b'-  where-    a' = subst x e a-    b' = subst x e b-subst x e (Prefer a b) = Prefer a' b'-  where-    a' = subst x e a-    b' = subst x e b-subst x e (Merge a b c) = Merge a' b' c'-  where-    a' =       subst x e  a-    b' =       subst x e  b-    c' = fmap (subst x e) c-subst x e (Field a b) = Field a' b-  where-    a' = subst x e a-subst x e (Project a b) = Project a' b-  where-    a' = subst x e a-subst x e (Note a b) = Note a b'-  where-    b' = subst x e b-subst x e (ImportAlt a b) = ImportAlt a' b'-  where-    a' = subst x e a-    b' = subst x e b--- The Dhall compiler enforces that all embedded values are closed expressions--- and `subst` does nothing to a closed expression-subst _ _ (Embed p) = Embed p--{-| α-normalize an expression by renaming all 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 = Dhall.Eval.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.--    However, `normalize` will not fail if the expression is ill-typed and will-    leave ill-typed sub-expressions unevaluated.--}--normalize :: Eq a => Expr s a -> Expr t a-normalize = Dhall.Eval.nfEmpty---{-| 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---- | Remove all `Note` constructors from an `Expr` (i.e. de-`Note`)-denote :: Expr s a -> Expr t a-denote (Note _ b            ) = denote b-denote (Const a             ) = Const a-denote (Var a               ) = Var a-denote (Lam a b c           ) = Lam a (denote b) (denote c)-denote (Pi a b c            ) = Pi a (denote b) (denote c)-denote (App a b             ) = App (denote a) (denote b)-denote (Let as b            ) = Let (fmap f as) (denote b)-  where-    f (Binding c d e) = Binding c (fmap denote d) (denote e)-denote (Annot a b           ) = Annot (denote a) (denote b)-denote  Bool                  = Bool-denote (BoolLit a           ) = BoolLit a-denote (BoolAnd a b         ) = BoolAnd (denote a) (denote b)-denote (BoolOr a b          ) = BoolOr (denote a) (denote b)-denote (BoolEQ a b          ) = BoolEQ (denote a) (denote b)-denote (BoolNE a b          ) = BoolNE (denote a) (denote b)-denote (BoolIf a b c        ) = BoolIf (denote a) (denote b) (denote c)-denote  Natural               = Natural-denote (NaturalLit a        ) = NaturalLit a-denote  NaturalFold           = NaturalFold-denote  NaturalBuild          = NaturalBuild-denote  NaturalIsZero         = NaturalIsZero-denote  NaturalEven           = NaturalEven-denote  NaturalOdd            = NaturalOdd-denote  NaturalToInteger      = NaturalToInteger-denote  NaturalShow           = NaturalShow-denote (NaturalPlus a b     ) = NaturalPlus (denote a) (denote b)-denote (NaturalTimes a b    ) = NaturalTimes (denote a) (denote b)-denote  Integer               = Integer-denote (IntegerLit a        ) = IntegerLit a-denote  IntegerShow           = IntegerShow-denote  IntegerToDouble       = IntegerToDouble-denote  Double                = Double-denote (DoubleLit a         ) = DoubleLit a-denote  DoubleShow            = DoubleShow-denote  Text                  = Text-denote (TextLit (Chunks a b)) = TextLit (Chunks (fmap (fmap denote) a) b)-denote (TextAppend a b      ) = TextAppend (denote a) (denote b)-denote  TextShow              = TextShow-denote  List                  = List-denote (ListLit a b         ) = ListLit (fmap denote a) (fmap denote b)-denote (ListAppend a b      ) = ListAppend (denote a) (denote b)-denote  ListBuild             = ListBuild-denote  ListFold              = ListFold-denote  ListLength            = ListLength-denote  ListHead              = ListHead-denote  ListLast              = ListLast-denote  ListIndexed           = ListIndexed-denote  ListReverse           = ListReverse-denote  Optional              = Optional-denote (OptionalLit a b     ) = OptionalLit (denote a) (fmap denote b)-denote (Some a              ) = Some (denote a)-denote  None                  = None-denote  OptionalFold          = OptionalFold-denote  OptionalBuild         = OptionalBuild-denote (Record a            ) = Record (fmap denote a)-denote (RecordLit a         ) = RecordLit (fmap denote a)-denote (Union a             ) = Union (fmap (fmap denote) a)-denote (UnionLit a b c      ) = UnionLit a (denote b) (fmap (fmap denote) c)-denote (Combine a b         ) = Combine (denote a) (denote b)-denote (CombineTypes a b    ) = CombineTypes (denote a) (denote b)-denote (Prefer a b          ) = Prefer (denote a) (denote b)-denote (Merge a b c         ) = Merge (denote a) (denote b) (fmap denote c)-denote (Field a b           ) = Field (denote a) b-denote (Project a b         ) = Project (denote a) (fmap denote b)-denote (ImportAlt a b       ) = ImportAlt (denote a) (denote b)-denote (Embed a             ) = Embed a--{-| Reduce an expression to its normal form, performing beta reduction and applying-    any custom definitions.--    `normalizeWith` is designed to be used with function `typeWith`. The `typeWith`-    function allows typing of Dhall functions in a custom typing context whereas-    `normalizeWith` allows evaluating Dhall expressions in a custom context.--    To be more precise `normalizeWith` applies the given normalizer when it finds an-    application term that it cannot reduce by other means.--    Note that the context used in normalization will determine the properties of normalization.-    That is, if the functions in custom context are not total then the Dhall language, evaluated-    with those functions is not total either.---}-normalizeWith :: Eq a => Maybe (ReifiedNormalizer a) -> Expr s a -> Expr t a-normalizeWith (Just ctx) t = runIdentity (normalizeWithM (getReifiedNormalizer ctx) t)-normalizeWith _          t = Dhall.Eval.nfEmpty t--normalizeWithM-    :: (Monad m, Eq a) => NormalizerM m a -> Expr s a -> m (Expr t a)-normalizeWithM ctx e0 = loop (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-                    -- build/fold fusion for `List`-                    App (App ListBuild _) (App (App ListFold _) e') -> loop e'--                    -- build/fold fusion for `Natural`-                    App NaturalBuild (App NaturalFold e') -> loop e'--                    -- build/fold fusion for `Optional`-                    App (App OptionalBuild _) (App (App OptionalFold _) e') -> loop e'--                    App (App (App (App NaturalFold (NaturalLit n0)) t) succ') zero -> do-                      t' <- loop t-                      if boundedType t' then strict else lazy-                      where-                        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 "x" Natural (NaturalPlus "x" (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 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-                    App IntegerToDouble (IntegerLit n) -> pure (DoubleLit ((read . show) n))-                    App DoubleShow (DoubleLit 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 _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 _A₁ 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 _A₂-                          | otherwise = Nothing--                        adapt n a_ =-                            RecordLit (Dhall.Map.fromList kvs)-                          where-                            kvs = [ ("index", NaturalLit (fromIntegral n))-                                  , ("value", a_)-                                  ]-                    App (App ListReverse t) (ListLit _ xs) ->-                        loop (ListLit m (Data.Sequence.reverse xs))-                      where-                        m = if Data.Sequence.null xs then Just t else Nothing-                    App (App (App (App (App OptionalFold _) (App None _)) _) _) nothing ->-                        loop nothing-                    App (App (App (App (App OptionalFold _) (Some x)) _) just) _ ->-                        loop (App just x)-                    App TextShow (TextLit (Chunks [] oldText)) ->-                        loop (TextLit (Chunks [] newText))-                      where-                        newText = textShow oldText-                    _ -> do-                        res2 <- ctx (App f' a')-                        case res2 of-                            Nothing -> pure (App f' a')-                            Just app' -> loop app'-    Let (Binding x _ a₀ :| ls₀) b₀ -> do-        a₁ <- loop a₀--        rest <- case ls₀ of-                []       -> loop b₀-                l₁ : ls₁ -> loop (Let (l₁ :| ls₁) b₀)--        let a₂ = shift 1 (V x 0) a₁-        let b₁ = subst (V x 0) a₂ rest-        let b₂ = shift (-1) (V x 0) b₁--        loop 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-            | judgmentallyEqual l r = l-            | otherwise             = BoolAnd l r-    BoolOr x y -> decide <$> loop x <*> loop y-      where-        decide (BoolLit False)  r              = r-        decide (BoolLit True )  _              = BoolLit True-        decide  l              (BoolLit False) = l-        decide  _              (BoolLit True ) = BoolLit True-        decide  l               r-            | judgmentallyEqual l r = l-            | otherwise             = BoolOr l r-    BoolEQ x y -> decide <$> loop x <*> loop y-      where-        decide (BoolLit True )  r              = r-        decide  l              (BoolLit True ) = l-        decide  l               r-            | judgmentallyEqual l r = BoolLit True-            | otherwise             = BoolEQ l r-    BoolNE x y -> decide <$> loop x <*> loop y-      where-        decide (BoolLit False)  r              = r-        decide  l              (BoolLit False) = l-        decide  l               r-            | judgmentallyEqual l r = BoolLit False-            | otherwise             = BoolNE l r-    BoolIf bool true false -> decide <$> loop bool <*> loop true <*> loop false-      where-        decide (BoolLit True )  l              _              = l-        decide (BoolLit False)  _              r              = r-        decide  b              (BoolLit True) (BoolLit False) = b-        decide  b               l              r-            | judgmentallyEqual l r = l-            | otherwise             = BoolIf b l r-    Natural -> 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-    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)-    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' <*> es'-        | 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-    OptionalLit _A Nothing -> loop (App None _A)-    OptionalLit _ (Just a) -> loop (Some a)-    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-    UnionLit k v kvs -> UnionLit k <$> v' <*> (Dhall.Map.sort <$> kvs')-      where-        v'   =                    loop  v-        kvs' = traverse (traverse loop) kvs-    Combine 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.sort (Dhall.Map.unionWith decide m n))-        decide l r =-            Combine 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.sort (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.sort (Dhall.Map.union n m))-        decide l r =-            Prefer l r-    Merge x y t      -> do-        x' <- loop x-        y' <- loop y-        case x' of-            RecordLit kvsX ->-                case y' of-                    UnionLit kY vY _ ->-                        case Dhall.Map.lookup kY kvsX of-                            Just vX -> loop (App vX vY)-                            Nothing -> Merge x' y' <$> t'-                    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'-                    _ -> Merge x' y' <$> t'-            _ -> Merge x' y' <$> t'-      where-        t' = traverse loop t-    Field r x        -> do-        r' <- loop r-        case r' of-            RecordLit kvs ->-                case Dhall.Map.lookup x kvs of-                    Just v  -> loop v-                    Nothing -> Field <$> (RecordLit <$> traverse loop kvs) <*> pure x-            _ -> pure (Field r' x)-    Project r (Left xs)-> do-        r' <- loop r-        case r' of-            RecordLit kvs ->-                case traverse adapt (Dhall.Set.toList xs) of-                    Just s  ->-                        loop (RecordLit kvs')-                      where-                        kvs' = Dhall.Map.fromList s-                    Nothing ->-                        Project <$> (RecordLit <$> traverse loop kvs) <*> pure (Left xs)-              where-                adapt x = do-                    v <- Dhall.Map.lookup x kvs-                    return (x, v)-            _   | null xs -> pure (RecordLit mempty)-                | otherwise -> pure (Project r' (Left xs))-    Project r (Right e1) -> do-        e2 <- loop e1--        case e2 of-            Record kts -> do-                loop (Project r (Left (Dhall.Set.fromList (Dhall.Map.keys kts))))-            _ -> do-                r' <- loop r-                pure (Project r' (Right e2))-    Note _ e' -> loop e'-    ImportAlt l _r -> loop l-    Embed a -> pure (Embed a)--textShow :: Text -> Text-textShow text = "\"" <> Data.Text.concatMap f text <> "\""-  where-    f '"'  = "\\\""-    f '$'  = "\\u0024"-    f '\\' = "\\\\"-    f '\b' = "\\b"-    f '\n' = "\\n"-    f '\r' = "\\r"-    f '\t' = "\\t"-    f '\f' = "\\f"-    f c | c <= '\x1F' = Data.Text.pack (Text.Printf.printf "\\u%04x" (Data.Char.ord c))-        | otherwise   = Data.Text.singleton c--{-| Returns `True` if two expressions are α-equivalent and β-equivalent and-    `False` otherwise--}-judgmentallyEqual :: Eq a => Expr s a -> Expr t a -> Bool-judgmentallyEqual = Dhall.Eval.convEmpty---- | 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))--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 :: (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-isNormalized :: Eq a => Expr s a -> Bool-isNormalized e0 = loop (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--          -- build/fold fusion for `List`-          App (App ListBuild _) (App (App ListFold _) _) -> False--          -- build/fold fusion for `Natural`-          App NaturalBuild (App NaturalFold _) -> False--          -- build/fold fusion for `Optional`-          App (App OptionalBuild _) (App (App OptionalFold _) _) -> False--          App (App (App (App NaturalFold (NaturalLit _)) _) _) _ -> False-          App NaturalBuild _ -> False-          App NaturalIsZero (NaturalLit _) -> False-          App NaturalEven (NaturalLit _) -> False-          App NaturalOdd (NaturalLit _) -> False-          App NaturalShow (NaturalLit _) -> False-          App NaturalToInteger (NaturalLit _) -> False-          App IntegerShow (IntegerLit _) -> False-          App IntegerToDouble (IntegerLit _) -> False-          App DoubleShow (DoubleLit _) -> False-          App (App OptionalBuild _) _ -> False-          App (App ListBuild _) _ -> False-          App (App (App (App (App ListFold _) (ListLit _ _)) _) _) _ ->-              False-          App (App ListLength _) (ListLit _ _) -> False-          App (App ListHead _) (ListLit _ _) -> False-          App (App ListLast _) (ListLit _ _) -> False-          App (App ListIndexed _) (ListLit _ _) -> False-          App (App ListReverse _) (ListLit _ _) -> False-          App (App (App (App (App OptionalFold _) (Some _)) _) _) _ ->-              False-          App (App (App (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 (judgmentallyEqual l r)-      BoolOr x y -> loop x && loop y && decide x y-        where-          decide (BoolLit _)  _          = False-          decide  _          (BoolLit _) = False-          decide  l           r          = not (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 (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 (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 (judgmentallyEqual l r)-      Natural -> True-      NaturalLit _ -> True-      NaturalFold -> True-      NaturalBuild -> True-      NaturalIsZero -> True-      NaturalEven -> True-      NaturalOdd -> True-      NaturalShow -> 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-      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-      OptionalLit _ _ -> False-      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-      UnionLit _ v kvs -> loop v && Dhall.Map.isSorted kvs && all (all loop) kvs-      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  _ _ = True-      Merge x y t -> loop x && loop y && all loop t &&-          case x of-              RecordLit kvsX ->-                  case y of-                      UnionLit kY _  _ ->-                          case Dhall.Map.lookup kY kvsX of-                              Just _  -> False-                              Nothing -> True-                      _ -> True-              _ -> True-      Field r x -> loop r &&-          case r of-              RecordLit kvs ->-                  case Dhall.Map.lookup x kvs of-                      Just _  -> False-                      Nothing -> True-              Union kvs ->-                  case Dhall.Map.lookup x kvs of-                      Just _  -> False-                      Nothing -> True-              _ -> True-      Project r xs -> loop r &&-          case r of-              RecordLit kvs ->-                  case xs of-                      Left  s -> not (all (flip Dhall.Map.member kvs) s)-                      Right e' ->-                          case e' of-                              Record kts ->-                                  loop (Project r (Left (Dhall.Set.fromList (Dhall.Map.keys kts))))-                              _ ->-                                  False-              _ -> not (null xs)-      Note _ e' -> loop e'-      ImportAlt l _r -> loop l-      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 `freeIn` expression =-    Dhall.Core.shift 1 variable strippedExpression /= strippedExpression-  where-    denote' :: Expr t b -> Expr () b-    denote' = denote--    strippedExpression = denote' 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 <> "                                                       "-    , "```                                                                             "-    ] )---- | The set of reserved identifiers for the Dhall language-reservedIdentifiers :: HashSet Text-reservedIdentifiers =-    Data.HashSet.fromList-        [ "let"-        , "in"-        , "Type"-        , "Kind"-        , "Sort"-        , "forall"-        , "Bool"-        , "True"-        , "False"-        , "merge"-        , "if"-        , "then"-        , "else"-        , "as"-        , "using"-        , "constructors"-        , "Natural"-        , "Natural/fold"-        , "Natural/build"-        , "Natural/isZero"-        , "Natural/even"-        , "Natural/odd"-        , "Natural/toInteger"-        , "Natural/show"-        , "Integer"-        , "Integer/show"-        , "Integer/toDouble"-        , "Double"-        , "Double/show"-        , "Text"-        , "Text/show"-        , "List"-        , "List/build"-        , "List/fold"-        , "List/length"-        , "List/head"-        , "List/last"-        , "List/indexed"-        , "List/reverse"-        , "Optional"-        , "Some"-        , "None"-        , "Optional/build"-        , "Optional/fold"-        , "NaN"-        , "Infinity"-        ]----- | 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 _ (Const c) = pure (Const c)-subExpressions _ (Var v) = pure (Var v)-subExpressions f (Lam a b c) = Lam a <$> f b <*> f c-subExpressions f (Pi a b c) = Pi a <$> f b <*> f c-subExpressions f (App a b) = App <$> f a <*> f b-subExpressions f (Let as b) = Let <$> traverse g as <*> f b-  where-    g (Binding c d e) = Binding c <$> traverse f d <*> f e-subExpressions f (Annot a b) = Annot <$> f a <*> f b-subExpressions _ Bool = pure Bool-subExpressions _ (BoolLit b) = pure (BoolLit b)-subExpressions f (BoolAnd a b) = BoolAnd <$> f a <*> f b-subExpressions f (BoolOr a b) = BoolOr <$> f a <*> f b-subExpressions f (BoolEQ a b) = BoolEQ <$> f a <*> f b-subExpressions f (BoolNE a b) = BoolNE <$> f a <*> f b-subExpressions f (BoolIf a b c) = BoolIf <$> f a <*> f b <*> f c-subExpressions _ Natural = pure Natural-subExpressions _ (NaturalLit n) = pure (NaturalLit n)-subExpressions _ NaturalFold = pure NaturalFold-subExpressions _ NaturalBuild = pure NaturalBuild-subExpressions _ NaturalIsZero = pure NaturalIsZero-subExpressions _ NaturalEven = pure NaturalEven-subExpressions _ NaturalOdd = pure NaturalOdd-subExpressions _ NaturalToInteger = pure NaturalToInteger-subExpressions _ NaturalShow = pure NaturalShow-subExpressions f (NaturalPlus a b) = NaturalPlus <$> f a <*> f b-subExpressions f (NaturalTimes a b) = NaturalTimes <$> f a <*> f b-subExpressions _ Integer = pure Integer-subExpressions _ (IntegerLit n) = pure (IntegerLit n)-subExpressions _ IntegerShow = pure IntegerShow-subExpressions _ IntegerToDouble = pure IntegerToDouble-subExpressions _ Double = pure Double-subExpressions _ (DoubleLit n) = pure (DoubleLit n)-subExpressions _ DoubleShow = pure DoubleShow-subExpressions _ Text = pure Text-subExpressions f (TextLit chunks) =-    TextLit <$> chunkExprs f chunks-subExpressions f (TextAppend a b) = TextAppend <$> f a <*> f b-subExpressions _ TextShow = pure TextShow-subExpressions _ List = pure List-subExpressions f (ListLit a b) = ListLit <$> traverse f a <*> traverse f b-subExpressions f (ListAppend a b) = ListAppend <$> f a <*> f b-subExpressions _ ListBuild = pure ListBuild-subExpressions _ ListFold = pure ListFold-subExpressions _ ListLength = pure ListLength-subExpressions _ ListHead = pure ListHead-subExpressions _ ListLast = pure ListLast-subExpressions _ ListIndexed = pure ListIndexed-subExpressions _ ListReverse = pure ListReverse-subExpressions _ Optional = pure Optional-subExpressions f (OptionalLit a b) = OptionalLit <$> f a <*> traverse f b-subExpressions f (Some a) = Some <$> f a-subExpressions _ None = pure None-subExpressions _ OptionalFold = pure OptionalFold-subExpressions _ OptionalBuild = pure OptionalBuild-subExpressions f (Record a) = Record <$> traverse f a-subExpressions f ( RecordLit a ) = RecordLit <$> traverse f a-subExpressions f (Union a) = Union <$> traverse (traverse f) a-subExpressions f (UnionLit a b c) =-    UnionLit a <$> f b <*> traverse (traverse f) c-subExpressions f (Combine a b) = Combine <$> f a <*> f b-subExpressions f (CombineTypes a b) = CombineTypes <$> f a <*> f b-subExpressions f (Prefer a b) = Prefer <$> f a <*> f b-subExpressions f (Merge a b t) = Merge <$> f a <*> f b <*> traverse f t-subExpressions f (Field a b) = Field <$> f a <*> pure b-subExpressions f (Project a b) = Project <$> f a <*> pure b-subExpressions f (Note a b) = Note a <$> f b-subExpressions f (ImportAlt l r) = ImportAlt <$> f l <*> f r-subExpressions _ (Embed a) = pure (Embed a)---- | 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--{-| 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'--prettyPathComponent :: Text -> Doc ann-prettyPathComponent text-    | Data.Text.all pathCharacter text =-        "/" <> Pretty.pretty text-    | otherwise =-        "/\"" <> Pretty.pretty text <> "\""--prettyURIComponent :: Text -> Doc ann-prettyURIComponent text-    | Data.Text.all (\c -> pathCharacter c && URI.Encode.isAllowed c) text =-        "/" <> Pretty.pretty text-    | otherwise =-        "/\"" <> Pretty.pretty text <> "\""--{-| Convenience utility for converting `Either`-based exceptions to `IO`-based-    exceptions--}-throws :: (Exception e, MonadIO io) => Either e a -> io a-throws (Left  e) = liftIO (Control.Exception.throwIO e)-throws (Right r) = return r+{-# LANGUAGE RankNTypes      #-}+{-# LANGUAGE RecordWildCards #-}++{-| This module contains the core calculus for the Dhall language.++    Dhall is essentially a fork of the @morte@ compiler but with more built-in+    functionality, better error messages, and Haskell integration+-}++module Dhall.Core (+    -- * Syntax+      Const(..)+    , Directory(..)+    , File(..)+    , FilePrefix(..)+    , Import(..)+    , ImportHashed(..)+    , ImportMode(..)+    , ImportType(..)+    , URL(..)+    , Scheme(..)+    , DhallDouble(..)+    , Var(..)+    , Binding(..)+    , makeBinding+    , Chunks(..)+    , PreferAnnotation(..)+    , RecordField(..)+    , makeRecordField+    , FunctionBinding(..)+    , makeFunctionBinding+    , FieldSelection (..)+    , makeFieldSelection+    , WithComponent (..)+    , Expr(..)++    -- * Normalization+    , alphaNormalize+    , normalize+    , normalizeWith+    , normalizeWithM+    , Normalizer+    , NormalizerM+    , ReifiedNormalizer (..)+    , judgmentallyEqual+    , subst+    , shift+    , isNormalized+    , isNormalizedWith+    , denote+    , renote+    , shallowDenote+    , freeIn++    -- * Pretty-printing+    , pretty++    -- * Optics+    , subExpressions+    , subExpressionsWith+    , chunkExprs+    , bindingExprs+    , recordFieldExprs+    , functionBindingExprs++    -- * Let-blocks+    , multiLet+    , wrapInLets+    , MultiLet(..)++    -- * Miscellaneous+    , internalError+    , reservedIdentifiers+    , escapeText+    , pathCharacter+    , throws+    , Eval.textShow+    , censorExpression+    , censorText+    ) where++import Control.Exception      (Exception)+import Control.Monad.IO.Class (MonadIO (..))+import Data.Text              (Text)+import Dhall.Normalize+import Dhall.Pretty.Internal+import Dhall.Src              (Src (..))+import Dhall.Syntax+import Instances.TH.Lift      ()+import Lens.Micro             (over)+import Prettyprinter          (Pretty)++import qualified Control.Exception+import qualified Data.Text+import qualified Dhall.Eval        as Eval++-- | Pretty-print a value+pretty :: Pretty a => a -> Text+pretty = pretty_+{-# INLINE pretty #-}++{-| Escape a `Data.Text.Text` literal using Dhall's escaping rules++    Note that the result does not include surrounding quotes+-}+escapeText :: Text -> Text+escapeText = escapeText_+{-# INLINE escapeText #-}+++{-| Utility used to implement the @--censor@ flag, by:++    * Replacing all `Src` text with spaces+    * Replacing all `Dhall.Syntax.Text` literals inside type errors with spaces+-}+censorExpression :: Expr Src a -> Expr Src a+censorExpression (TextLit chunks) = TextLit (censorChunks chunks)+censorExpression (Note src     e) = Note (censorSrc src) (censorExpression e)+censorExpression  e               = over subExpressions censorExpression e++censorChunks :: Chunks Src a -> Chunks Src a+censorChunks (Chunks xys z) = Chunks xys' z'+  where+    z' = censorText z++    xys' = [ (censorText x, censorExpression y) | (x, y) <- xys ]++{-| Utility used to censor `Data.Text.Text` by replacing all characters with a+    space+-}+censorText :: Text -> Text+censorText = Data.Text.map (\_ -> ' ')++censorSrc :: Src -> Src+censorSrc (Src { srcText = oldText, .. }) = Src { srcText = newText, .. }+  where+    newText = censorText oldText++{-| Convenience utility for converting `Either`-based exceptions to `IO`-based+    exceptions+-}+throws :: (Exception e, MonadIO io) => Either e a -> io a+throws (Left  e) = liftIO (Control.Exception.throwIO e)+throws (Right r) = return r+{-# INLINABLE throws #-}++{- $setup+>>> import qualified Codec.Serialise+>>> import qualified Dhall.Binary+>>> import Data.SpecialValues+>>> import Test.QuickCheck (Arbitrary(..), oneof, elements)+>>> :{+  instance Arbitrary DhallDouble where+    arbitrary = fmap DhallDouble (oneof [ arbitrary, elements specialValues ])+:}+-}
− src/Dhall/Core.hs-boot
@@ -1,11 +0,0 @@-module Dhall.Core where--data Const--data Var--data Expr s a--data Import--denote :: Expr s a -> Expr t a
+ src/Dhall/Deriving.hs view
@@ -0,0 +1,547 @@+{-# LANGUAGE AllowAmbiguousTypes  #-}+{-# LANGUAGE DataKinds            #-}+{-# LANGUAGE FlexibleContexts     #-}+{-# LANGUAGE PolyKinds            #-}+{-# LANGUAGE ScopedTypeVariables  #-}+{-# LANGUAGE TypeApplications     #-}+{-# LANGUAGE TypeOperators        #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE UndecidableInstances #-}++{-| Newtypes for writing customizable 'FromDhall' and 'ToDhall' instances+    through the DerivingVia strategy.++    Inspired by Matt Parson's blog post+    [Mirror Mirror: Reflection and Encoding Via](https://www.parsonsmatt.org/2020/02/04/mirror_mirror.html),+    but applied to Dhall instead of JSON.++    This module is intended to be used with+    [DerivingVia](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#extension-DerivingVia)+    so it's only available for GHC >= v8.6.1.++    Check the section /Letting DerivingVia do the work/ if you want to see this module in action. (Click "Dhall.Deriving#derivingVia" to jump there)++-}++module Dhall.Deriving+  (+    -- * Introduction+    -- $introduction++    -- * Writing FromDhall instances by hand+    -- $instancesByHand++    -- * Letting DerivingVia do the work+    -- $derivingVia++    -- * Behind the scenes of Codec+    -- $behindTheScenes++    -- * DerivingVia newtype+    Codec (..)++    -- * Type-level functions on InterpretOptions+  , ModifyOptions (..)+  , Field+  , Constructor+  , SetSingletonConstructors++    -- * Type-level functions on Text+  , TextFunction (..)+  , DropPrefix+  , TitleCase+  , CamelCase+  , PascalCase+  , SnakeCase+  , SpinalCase+  , TrainCase++    -- * Type-level versions of SingletonConstructors+  , ToSingletonConstructors(..)+  , Bare+  , Wrapped+  , Smart++    -- * Identity and Composition for ModifyOptions and TextFunction+  , AsIs+  , type (<<<)++    -- * Helper function on Text+  , dropPrefix++    -- * InterpretOptions setters+  , addFieldModifier+  , addConstructorModifier+  , setSingletonConstructors++  ) where++import Data.Proxy   (Proxy (..))+import Dhall+import GHC.Generics (Generic (Rep))+import GHC.TypeLits (KnownSymbol, Symbol, symbolVal)++import qualified Data.Text            as Text+import qualified Data.Text.Manipulate as Case++-- | Intended for use on @deriving via@ clauses for types with a+--   'Generic' instance. The @tag@ argument is used to construct an+--   'InterpretOptions' value which is used as the first argument+--   to 'genericAutoWith'.+newtype Codec tag a = Codec { unCodec :: a }++instance (Generic a, GenericFromDhall a (Rep a), ModifyOptions tag) => FromDhall (Codec tag a) where+  autoWith _ = Codec <$> genericAutoWith (modifyOptions @tag defaultInterpretOptions)++instance (Generic a, GenericToDhall (Rep a), ModifyOptions tag) => ToDhall (Codec tag a) where+  injectWith _ = unCodec >$< genericToDhallWith (modifyOptions @tag defaultInterpretOptions)++-- | Convert a type into a @InterpretOptions -> InterpretOptions@ function+class ModifyOptions a where+  modifyOptions :: InterpretOptions -> InterpretOptions+++-- | The identity for functions on 'InterpretOptions' and on @Text@.+--   Useful for deriving @FromDhall@ and @ToDhall@ with the default options.+type AsIs = ()++instance ModifyOptions AsIs where+  modifyOptions = id++instance TextFunction AsIs where+  textFunction = id+++-- | Composition for functions on 'InterpretOptions' and on @Text@.+--   We use @<<<@ since @.@ isn't a valid type operator yet+--   (it will be valid starting from ghc-8.8.1)+data a <<< b+infixr 1 <<<++instance (ModifyOptions a, ModifyOptions b) => ModifyOptions (a <<< b) where+  modifyOptions = modifyOptions @a . modifyOptions @b++instance (TextFunction a, TextFunction b) => TextFunction (a <<< b) where+  textFunction = textFunction @a . textFunction @b+++-- | @Field t@ post-composes the @fieldModifier@ from @options@ with the+--   value-level version of @t@, obtained with @TextFunction@+data Field a+instance TextFunction a => ModifyOptions (Field a) where+  modifyOptions = addFieldModifier (textFunction @a)++-- | @Constructor t@ post-composes the @constructorModifier@ from @options@+--   with the value-level version of @t@, obtained with @TextFunction@+data Constructor a+instance TextFunction a => ModifyOptions (Constructor a) where+  modifyOptions = addConstructorModifier (textFunction @a)+++-- * Text Functions++-- | Convert a type into a @Text -> Text@ function+class TextFunction a where+  textFunction :: Text -> Text++-- | @DropPrefix prefix@ corresponds to the value level+--   function @'dropPrefix' prefix@+data DropPrefix (s :: Symbol)+instance KnownSymbol s => TextFunction (DropPrefix s) where+  textFunction = dropPrefix (Text.pack (symbolVal @s Proxy))++-- | Convert casing to @Title Cased Phrase@+data TitleCase+instance TextFunction TitleCase where+  textFunction = Case.toTitle++-- | Convert casing to @camelCasedPhrase@+data CamelCase+instance TextFunction CamelCase where+  textFunction = Case.toCamel++-- | Convert casing to @PascalCasedPhrase@+data PascalCase+instance TextFunction PascalCase where+  textFunction = Case.toPascal++-- | Convert casing to @snake_cased_phrase@+data SnakeCase+instance TextFunction SnakeCase where+  textFunction = Case.toSnake++-- | Convert casing to @spinal-cased-phrase@+data SpinalCase+instance TextFunction SpinalCase where+  textFunction = Case.toSpinal++-- | Convert casing to @Train-Cased-Phrase@+data TrainCase+instance TextFunction TrainCase where+  textFunction = Case.toTrain+++-- | @SetSingletonConstructors t@ replaces the @singletonConstructors@+--  from @options@ with the value-level version of @t@.+data SetSingletonConstructors a+instance ToSingletonConstructors a => ModifyOptions (SetSingletonConstructors a) where+  modifyOptions = setSingletonConstructors (asSingletonConstructors @a)++-- | Convert a type of kind @SingletonConstructors@+--   into a value of type @SingletonConstructors@+class ToSingletonConstructors (a :: SingletonConstructors) where+  asSingletonConstructors :: SingletonConstructors++-- | Type-level version of 'Dhall.Bare'.+-- Never wrap the field of a singleton constructor in a record+type Bare = 'Bare+instance ToSingletonConstructors Bare where+  asSingletonConstructors = Bare++-- | Type-level version of 'Dhall.Wrapped'+-- Always wrap the field of a singleton constructor in a record+type Wrapped = 'Wrapped+instance ToSingletonConstructors Wrapped where+  asSingletonConstructors = Wrapped++-- | Type-level version of 'Dhall.Smart'+-- Wrap the field of a singleton constructor in a record+-- only if the field is named+type Smart = 'Smart+instance ToSingletonConstructors Smart where+  asSingletonConstructors = Smart+++-- * Text helper++-- | @dropPrefix prefix text@ returns the suffix of @text@ if its prefix+--   matches @prefix@, or the entire @text@ otherwise+dropPrefix :: Text -> (Text -> Text)+dropPrefix prefix text = case Text.stripPrefix prefix text of+  Nothing -> text+  Just e -> e++-- * InterpretOptions setters++-- | @addFieldModifier f options@ post-composes the @fieldModifier@+--  from @options@ with @f@.+addFieldModifier :: (Text -> Text) -> InterpretOptions -> InterpretOptions+addFieldModifier f options = options+  { fieldModifier = f . fieldModifier options }++-- | @addConstructorModifier f options@ post-composes the @constructorModifier@+--   from @options@ with @f@.+addConstructorModifier :: (Text -> Text) -> InterpretOptions -> InterpretOptions+addConstructorModifier f options = options+  { constructorModifier = f . constructorModifier options }++-- | @setSingletonConstructors v options@ replaces the @singletonConstructors@+--  from @options@ with @v@.+setSingletonConstructors :: SingletonConstructors -> InterpretOptions -> InterpretOptions+setSingletonConstructors v options = options+  { singletonConstructors = v }++{- $introduction++Let's take the following Haskell data types:++>>> :set -XDerivingStrategies++>>> :{+newtype Name = Name { getName :: Text }+  deriving stock (Show)+:}++>>> :{+data Font = Arial | ComicSans | Helvetica | TimesNewRoman+  deriving stock (Show)+:}++>>> :{+data Person = Person+  { personName :: Name+  , personFavoriteFont :: Font+  }+  deriving stock (Show)+:}++And assume we want to read the following Dhall file as a @Person@:++@+-- ./simon.dhall+let Name = Text+let Font = \< Arial | `Comic Sans` | Helvetica | `Times New Roman` \>+let Person = { name : Name, favoriteFont : Font }+in  { name = \"Simon\", favoriteFont = Font.`Comic Sans` } : Person+@++Usually, you would build a 'Decoder' by hand, like this++>>> :{+font :: Decoder Font+font =+  union+    (  (Arial         <$ constructor "Arial"           unit)+    <> (ComicSans     <$ constructor "Comic Sans"      unit)+    <> (Helvetica     <$ constructor "Helvetica"       unit)+    <> (TimesNewRoman <$ constructor "Times New Roman" unit)+    )+:}++>>> :{+name :: Decoder Name+name = Name <$> strictText+:}++>>> :{+person :: Decoder Person+person =+  record+    ( Person <$> field "name"         name+             <*> field "favoriteFont" font+    )+:}++and then you use it like this++>>> input person "./simon.dhall"+Person {personName = Name {getName = "Simon"}, personFavoriteFont = ComicSans}++So, it works! However, this is quite mechanic, and the compiler has pretty+much all the information it needs to do it for you. Besides, you'd like to+provide an instance of 'FromDhall' so you can use the polymorphic 'Decoder'+'auto' instead of explicitly calling @person@.+-}++{- $instancesByHand+"Aha!," you think, "I'll write an empty @instance 'FromDhall' Person@".+That in turn requires you to add two other instances for @Font@ and for @Name@,+plus 'Generic' instances for each of those, but that's okay.++>>> :set -XStandaloneDeriving+>>> :set -XDeriveGeneric++>>> :{+deriving stock instance Generic Name+deriving stock instance Generic Font+deriving stock instance Generic Person+:}++>>> :{+instance FromDhall Name+instance FromDhall Font+instance FromDhall Person+:}++However, when you try to read the same file with 'auto', you get this:++>>> input auto "./simon.dhall" :: IO Person+*** Exception:+...Error...: Expression doesn't match annotation+...+{ - personFavoriteFont : …+, - personName : …+, + favoriteFont : …+, + name : …+}+...+1│ ./simon.dhall : { personName : { getName : Text }+2│ , personFavoriteFont : < Arial | ComicSans | Helvetica | TimesNewRoman >+3│ }+...++What happened? The field names don't quite match, since we're using prefixed+field names in Haskell but no prefixes in Dhall. "Okay," you think,+"I can write a custom instance which builds on 'Generic' thanks to+'genericAutoWith', I only need to supply a function to drop the prefixes+and @camelCase@ the rest". So, using 'Data.Text.Manipulate.toCamel':++>>> import Data.Text.Manipulate (toCamel)+>>> import qualified Data.Text as Text+>>> :{+instance FromDhall Person where+  autoWith _ =+    genericAutoWith defaultInterpretOptions+      { fieldModifier = toCamel . Text.drop (Text.length "person") }+:}++Let's try to read that again:++>>> input auto "./simon.dhall":: IO Person+*** Exception:+...Error...: Expression doesn't match annotation+...+{ favoriteFont : < - ComicSans : …+                 | - TimesNewRoman : …+                 | + `Comic Sans` : …+                 | + `Times New Roman` : …+                 | …+                 >+, name : - { … : … } (a record type)+         + Text+}+...+1│ ./simon.dhall : { name : { getName : Text }+2│ , favoriteFont : < Arial | ComicSans | Helvetica | TimesNewRoman >+3│ }+...++Okay, we're almost there. We have two things to solve now.+First, the @Font@ constructors are @PascalCased@ in Haskell,+but @Title Cased@ in Dhall. We can communicate this to our+'FromDhall' instance using 'Data.Text.Manipulate.toTitle':++>>> import Data.Text.Manipulate (toTitle)+>>> :{+instance FromDhall Font where+  autoWith _ =+    genericAutoWith defaultInterpretOptions+      { constructorModifier = toTitle }+:}++Second, we defined the @Name@ type in Haskell as a newtype over @Text@, with a+@getName@ field for unwrapping. In Dhall, however, @Name@ is a synonym of+'Data.Text.Text', which is why 'Dhall.input' above was expecting a record.+The 'Dhall.Bare' option for 'singletonConstructors' is a perfect fit here:+it translates Haskell singleton constructors into the Dhall version of the+nested type, without wrapping it into a record.+We can then tweak our 'FromDhall' instance like this:++>>> :{+instance FromDhall Name where+  autoWith _ =+    genericAutoWith defaultInterpretOptions+      { singletonConstructors = Bare }+:}++Since we're running this interactively, we also need to update the+instance for @Person@, but it's the same as before.++>>> :{+instance FromDhall Person where+  autoWith _ =+    genericAutoWith defaultInterpretOptions+      { fieldModifier = toCamel . Text.drop (Text.length "person") }+:}++Now, for the moment of truth:++>>> input auto "./simon.dhall":: IO Person+Person {personName = Name {getName = "Simon"}, personFavoriteFont = ComicSans}++That took a bit more work than we wanted, though, and a lot of it was just+boilerplate for defining the instances through `genericAutoWith`, tweaking+a single parameter at a time. Even worse, if we also wanted to provide+'ToDhall' instances we would need to keep the options in sync between both+instances, since otherwise the values wouldn't be able to round-trip from+Dhall to Dhall through Haskell.++-}++{- $derivingVia+   #derivingVia#++Starting with this dhall file:++@+-- ./simon.dhall+let Name = Text+let Font = \< Arial | `Comic Sans` | Helvetica | `Times New Roman` \>+let Person = { name : Name, favoriteFont : Font }+in  { name = \"Simon\", favoriteFont = Font.`Comic Sans` } : Person+@++We can define the equivalent Haskell types as follows. Note that we+derive the 'FromDhall' and 'ToDhall' instances @via 'Codec' tag TheType@,+using a different @tag@ depending on the transformations we need to apply to+the Haskell type to get the Dhall equivalent:++>>> :set -XDataKinds+>>> :set -XDeriveGeneric+>>> :set -XDerivingVia+>>> :set -XTypeOperators++>>> :{+newtype Name = Name { getName :: Text }+  deriving stock (Generic, Show)+  deriving (FromDhall, ToDhall)+    via Codec (SetSingletonConstructors Bare) Name+:}++>>> :{+data Font = Arial | ComicSans | Helvetica | TimesNewRoman+  deriving stock (Generic, Show)+  deriving (FromDhall, ToDhall)+    via Codec (Constructor TitleCase) Font+:}++>>> :{+data Person = Person+  { personName :: Name+  , personFavoriteFont :: Font+  }+  deriving stock (Generic, Show)+  deriving (FromDhall, ToDhall)+    via Codec (Field (CamelCase <<< DropPrefix "person")) Person+:}++we can then read the file using 'auto':++>>> simon <- input auto "./simon.dhall":: IO Person+>>> print simon+Person {personName = Name {getName = "Simon"}, personFavoriteFont = ComicSans}++And using 'inject' we can get @simon@ back as a Dhall value:++>>> import qualified Data.Text.IO as Text+>>> import Dhall.Core (pretty)+>>> Text.putStrLn . pretty . embed inject $ simon+{ name = "Simon"+, favoriteFont =+    < Arial | `Comic Sans` | Helvetica | `Times New Roman` >.`Comic Sans`+}++-}++{- $behindTheScenes++@'Codec' tag a@ is really just a newtype over @a@, equipped with a+phantom @tag@. The 'FromDhall' instance for 'Codec' uses the generic+representation of @a@, together with the 'InterpretOptions' defined by @tag@ as+a series of modifications to be applied on 'defaultInterpretOptions'.++For the default behavior, using 'AsIs' (a synonym for @()@) as the @tag@+leaves the interpret options alone, so it's equivalent to the empty instance+we first tried to use.++@'Field' a@ and @'Constructor' a@ can be used to modify, respectively, the+'fieldModifier' and 'constructorModifier' options of 'InterpretOptions', by+post-composing the modifier with @'textFunction' \@a@, that is, the value-level+equivalent of @a@, obtained through the 'TextFunction' class.++In the case of @Person@, we used++@+  Codec (Field (CamelCase <<< DropPrefix "person")) Person+@++which means that the @Text -> Text@ version of++@+  CamelCase <<< DropPrefix "person"+@++was used to modify the @fieldModifier@ option.++In the value level, this translates to composing ('<<<')+'Data.Text.Manipulate.toCamel' ('CamelCase') with @'dropPrefix' "person"@+(@'DropPrefix' "person"@).++Finally, @'SetSingletonConstructors' a@ can be used to set the+'singletonConstructors' option of 'InterpretOptions', by replacing the option+with the value-level equivalent of @a@.+-}++{- $setup+>>> :set -XOverloadedStrings+-}
src/Dhall/Diff.hs view
@@ -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@@ -12,44 +13,55 @@ module Dhall.Diff (     -- * Diff       Diff (..)-    , diffExpression     , diffNormalized-    , Dhall.Diff.diff+    , diff     ) where -import Data.Foldable (fold, toList)-import Data.Function (on)-import Data.List.NonEmpty (NonEmpty(..))-import Data.Monoid (Any(..))-import Data.Semigroup-import Data.Sequence (Seq)-import Data.String (IsString(..))-import Data.Text (Text)-import Data.Text.Prettyprint.Doc (Doc, Pretty)-import Dhall.Core (Binding(..), Chunks (..), Const(..), Expr(..), Var(..))-import Dhall.Binary (ToTerm)-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 Dhall.Core+import qualified Data.Time             as Time import qualified Dhall.Map-import qualified Dhall.Set-import qualified Dhall.Pretty.Internal      as Internal+import qualified Dhall.Normalize       as Normalize+import qualified Dhall.Pretty.Internal as Internal+import qualified Dhall.Syntax          as Syntax+import qualified Prettyprinter         as Pretty +{-| This type is a `Doc` enriched with a `same` flag to efficiently track if+    any difference was detected+-} data Diff =     Diff         { same :: Bool         , doc  :: Doc Ann         } -instance Data.Semigroup.Semigroup Diff where+instance Semigroup Diff where     Diff sameL docL <> Diff sameR docR = Diff (sameL && sameR) (docL <> docR)  instance Monoid (Diff) where@@ -59,10 +71,6 @@          doc = mempty -#if !(MIN_VERSION_base(4,11,0))-    mappend = (<>)-#endif- instance IsString (Diff) where     fromString string = Diff {..}       where@@ -117,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)@@ -154,17 +162,11 @@ rparen = token Internal.rparen  -- | Render the difference between the normal form of two expressions-diffNormalized :: (Eq a, Pretty a, ToTerm a) => Expr s a -> Expr s a -> Doc Ann+diffNormalized :: (Eq a, Pretty a) => Expr s a -> Expr s a -> Diff diffNormalized l0 r0 = Dhall.Diff.diff l1 r1   where-    l1 = Dhall.Core.alphaNormalize (Dhall.Core.normalize l0)-    r1 = Dhall.Core.alphaNormalize (Dhall.Core.normalize r0)---- | Render the difference between two expressions-diff :: (Eq a, Pretty a) => Expr s a -> Expr s a -> Doc Ann-diff l0 r0 = doc-  where-    Diff {..} = diffExpression l0 r0+    l1 = Normalize.alphaNormalize (Normalize.normalize l0)+    r1 = Normalize.alphaNormalize (Normalize.normalize r0)  diffPrimitive :: Eq a => (a -> Diff) -> a -> a -> Diff diffPrimitive f l r@@ -174,27 +176,44 @@ 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) -diffDouble :: Double -> Double -> Diff-diffDouble = diffPrimitive (token . Internal.prettyDouble)+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) @@ -207,12 +226,16 @@ diffInteger :: Integer -> Integer -> Diff diffInteger = diffPrimitive (token . Internal.prettyNumber) +diffInt :: Int -> Int -> Diff+diffInt = diffPrimitive (token . Internal.prettyInt)+ diffVar :: Var -> Var -> Diff-diffVar (V xL nL) (V xR nR) = format mempty label <> "@" <> natural+diffVar (V xL nL) (V xR nR) =+    format mempty label <> if same natural then mempty else "@" <> natural   where     label = diffLabel xL xR -    natural = diffInteger nL nR+    natural = diffInt nL nR  diffPretty :: (Eq a, Pretty a) => a -> a -> Diff diffPretty = diffPrimitive (token . Pretty.pretty)@@ -253,10 +276,12 @@ diffKeyVals     :: (Eq a, Pretty a)     => Diff-    -> Map Text (Expr s a)-    -> Map Text (Expr s a)+    -> Map Text (RecordField Void a)+    -> Map Text (RecordField Void a)     -> [Diff]-diffKeyVals assign = diffKeysWith assign diffExpression+diffKeyVals assign kvsL kvsR = diffKeysWith assign diff+    (recordFieldValue <$> kvsL)+    (recordFieldValue <$> kvsR)  diffKeysWith     :: Diff@@ -267,8 +292,8 @@ diffKeysWith assign diffVals kvsL kvsR =     diffFieldNames <> diffFieldValues <> (if anyEqual then [ ignore ] else [])   where-    ksL = Data.Set.fromList (Dhall.Map.keys kvsL)-    ksR = Data.Set.fromList (Dhall.Map.keys kvsR)+    ksL = Dhall.Map.keysSet kvsL+    ksR = Dhall.Map.keysSet kvsR      extraL = Data.Set.difference ksL ksR     extraR = Data.Set.difference ksR ksL@@ -309,15 +334,8 @@ bracketed = enclosed (lbracket <> " ") (comma <> " ") rbracket  diffText :: Text -> Text -> Diff-diffText l r-  | null parts         = "\"\""-  | allDifferent parts = difference textSkeleton textSkeleton-  | allSame parts      = textSkeleton-  | otherwise          = "\"" <> foldMap prettyPart parts <> "\""+diffText l r = "\"" <> foldMap prettyPart parts <> "\""   where-    allDifferent = not . any isBoth-    allSame      = all isBoth-     -- TODO: check for color support from the TTY     colorDiff colorCode chars =             "\ESC["@@ -347,7 +365,7 @@  diffChunks     :: (Eq a, Pretty a)-    => Chunks s a -> Chunks s a -> Diff+    => Chunks Void a -> Chunks Void a -> Diff diffChunks cL cR   | null chunks             = "\"\""   | [c] <- chunks           = c@@ -358,30 +376,38 @@      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         (Left  x, Left y ) -> diffText x y-        (Right x, Right y) -> diffExpression x y+        (Right x, Right y) -> diff x y         _                  -> diffTextSkeleton +diffBytes :: ByteString -> ByteString -> Diff+diffBytes l r =+    "0x" <> diffText (Internal.prettyBase16 l) (Internal.prettyBase16 r)+ diffList     :: (Eq a, Pretty a)-    => Seq (Expr s a) -> Seq (Expr s a) -> Diff-diffList l r-  | allDifferent parts = difference listSkeleton listSkeleton-  | otherwise          = bracketed (foldMap diffPart parts)+    => Seq (Expr Void a) -> Seq (Expr Void a) -> Diff+diffList l r = bracketed (loop parts₀)   where-    allDifferent = any (not . isBoth)-     -- Sections of the list that are only in left, only in right, or in both-    parts =-        Algo.Diff.getGroupedDiffBy ((same .) . diffExpression) (toList l) (toList r)+    parts₀ = Algo.Diff.getGroupedDiffBy equal (toList l) (toList r) +    equal a b = same (diff a b)+     -- Render each element of a list using an extra rendering function f     prettyElems f = map (f . token . Internal.prettyExpr) +    loop [] =+        mempty+    loop (Algo.Diff.First as : Algo.Diff.Second bs : parts)+        | length as == length bs = zipWith diff as bs <> loop parts+    loop (part : parts) =+        diffPart part <> loop parts+     diffPart part =       case part of         -- Only present in left@@ -396,58 +422,22 @@         Algo.Diff.Both _ _        ->             pure ignore --- Helper function to check when a diff part is present on both sides-isBoth :: Algo.Diff.Diff a -> Bool-isBoth p-  | Algo.Diff.Both _ _ <- p = True-  | otherwise               = False- diffRecord     :: (Eq a, Pretty a)-    => Map Text (Expr s a) -> Map Text (Expr s 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 s a) -> Map Text (Expr s a) -> Diff+    => Map Text (RecordField Void a) -> Map Text (RecordField Void a) -> Diff diffRecordLit kvsL kvsR = braced (diffKeyVals equals kvsL kvsR)  diffUnion     :: (Eq a, Pretty a)-    => Map Text (Maybe (Expr s a)) -> Map Text (Maybe (Expr s a)) -> Diff+    => Map Text (Maybe (Expr Void a)) -> Map Text (Maybe (Expr Void a)) -> Diff diffUnion kvsL kvsR = angled (diffKeysWith colon diffVals kvsL kvsR)   where-    diffVals = diffMaybe (colon <> " ") diffExpression--diffUnionLit-    :: (Eq a, Pretty a)-    => Text-    -> Text-    -> Expr s a-    -> Expr s a-    -> Map Text (Maybe (Expr s a))-    -> Map Text (Maybe (Expr s a))-    -> Diff-diffUnionLit kL kR vL vR kvsL kvsR =-        langle-    <>  " "-    <>  format " " (diffLabel kL kR)-    <>  equals-    <>  " "-    <>  format " " (diffExpression vL vR)-    <>  halfAngled (diffKeysWith colon diffVals kvsL kvsR)-  where-    diffVals = diffMaybe (colon <> " ") diffExpression--    halfAngled = enclosed (pipe <> " ") (pipe <> " ") rangle--listSkeleton :: Diff-listSkeleton =-        lbracket-    <>  " "-    <>  ignore-    <>  " "-    <>  rbracket+    diffVals = diffMaybe (colon <> " ") diff  textSkeleton :: Diff textSkeleton =@@ -469,12 +459,14 @@     <>  rarrow     <>  " "     <>  ignore+    <> " (a function)" skeleton (Pi {}) =         ignore     <>  " "     <>  rarrow     <>  " "     <>  ignore+    <> " (a function type)" skeleton (App Optional _) =         "Optional "     <>  ignore@@ -545,6 +537,10 @@     <>  keyword "else"     <>  " "     <>  ignore+skeleton (BytesLit {}) =+        "0x\""+    <>  ignore+    <>  "\"" skeleton (NaturalPlus {}) =         ignore     <>  " "@@ -565,32 +561,26 @@     <>  operator "++"     <>  " "     <>  ignore-skeleton (ListLit {}) =-        listSkeleton-    <>  " "-    <>  colon-    <>  " "-    <>  builtin "List"-    <>  " "-    <>  ignore+skeleton (ListLit _ elems)+    | null elems =+            lbracket+        <>  rbracket+        <>  " "+        <>  colon+        <>  " "+        <>  ignore+    | otherwise =+            lbracket+        <>  " "+        <>  ignore+        <>  " "+        <>  rbracket skeleton (ListAppend {}) =         ignore     <>  " "     <>  operator "#"     <>  " "     <>  ignore-skeleton (OptionalLit {}) =-        lbracket-    <>  " "-    <>  ignore-    <>  " "-    <>  rbracket-    <>  " "-    <>  colon-    <>  " "-    <>  builtin "Optional"-    <>  " "-    <>  ignore skeleton (Record {}) =         lbrace     <>  " "@@ -601,6 +591,7 @@     <>  ignore     <>  " "     <>  rbrace+    <>  " (a record type)" skeleton (RecordLit {}) =         lbrace     <>  " "@@ -611,6 +602,7 @@     <>  ignore     <>  " "     <>  rbrace+    <> " (a record)" skeleton (Union {}) =         langle     <>  " "@@ -621,16 +613,7 @@     <>  ignore     <>  " "     <>  rangle-skeleton (UnionLit {}) =-        langle-    <>  " "-    <>  ignore-    <>  " "-    <>  equals-    <>  " "-    <>  ignore-    <>  " "-    <>  rangle+    <> " (a union type)" skeleton (Combine {}) =         ignore     <>  " "@@ -649,12 +632,24 @@     <>  operator "⫽"     <>  " "     <>  ignore+skeleton (RecordCompletion {}) =+        ignore+    <>  operator "::"+    <>  ignore skeleton (Merge {}) =         keyword "merge"     <>  " "     <>  ignore     <>  " "     <>  ignore+skeleton (ToMap {}) =+        keyword "toMap"+    <>  " "+    <>  ignore+skeleton (ShowConstructor {}) =+        keyword "showConstructor"+    <>  " "+    <>  ignore skeleton (Field {}) =         ignore     <>  dot@@ -667,16 +662,25 @@     <>  ignore     <>  " "     <>  rbrace+skeleton (With {}) =+         ignore+    <>   " "+    <>   keyword "with"+    <>   " "+    <>   ignore skeleton x = token (Pretty.pretty x)  mismatch :: Pretty a => Expr s a -> Expr s a -> Diff mismatch l r = difference (skeleton l) (skeleton r) -diffExpression :: (Eq a, Pretty a) => Expr s a -> Expr s a -> Diff-diffExpression l@(Lam {}) r@(Lam {}) =+-- | Render the difference between two expressions+diff :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff+diff l@(Lam {}) r@(Lam {}) =     enclosed' "  " (rarrow <> " ") (docs l r)   where-    docs (Lam 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@@ -684,16 +688,16 @@             <>  format " " (diffLabel aL aR)             <>  colon             <>  " "-            <>  format mempty (diffExpression bL bR)+            <>  format mempty (diff bL bR)             <>  rparen      docs aL aR =-        pure (diffExpression aL aR)-diffExpression l@(Lam {}) r =+        pure (diff aL aR)+diff l@(Lam {}) r =     mismatch l r-diffExpression l r@(Lam {}) =+diff l r@(Lam {}) =     mismatch l r-diffExpression l@(BoolIf {}) r@(BoolIf {}) =+diff l@(BoolIf {}) r@(BoolIf {}) =     enclosed' "      " (keyword "else" <> "  ") (docs l r)   where     docs (BoolIf aL bL cL) (BoolIf aR bR cR) =@@ -701,98 +705,115 @@       where         doc =   keyword "if"             <>  " "-            <>  format " " (diffExpression aL aR)+            <>  format " " (diff aL aR)             <>  keyword "then"             <>  " "-            <>  diffExpression bL bR+            <>  diff bL bR     docs aL aR =-        pure (diffExpression aL aR)-diffExpression l@(BoolIf {}) r =+        pure (diff aL aR)+diff l@(BoolIf {}) r =     mismatch l r-diffExpression l r@(BoolIf {}) =+diff l r@(BoolIf {}) =     mismatch l r-diffExpression (Let asL bL ) (Let asR bR) =-    enclosed' "" (keyword "in" <> "  ")-        (Data.List.NonEmpty.zipWith docA asL asR <> pure docB)+diff l@(Let {}) r@(Let {}) =+    enclosed' "    " (keyword "in" <> "  ") (docs l r)   where-    docA (Binding cL dL eL) (Binding cR dR eR) = align doc+    docs (Let (Binding _ aL _ bL _ cL) dL) (Let (Binding _ aR _ bR _ cR) dR) =+        Data.List.NonEmpty.cons (align doc) (docs dL dR)       where+        bL' = fmap snd bL+        bR' = fmap snd bR+         doc =   keyword "let"             <>  " "-            <>  format " " (diffLabel cL cR)-            <>  format " " (diffMaybe (colon <> " ") diffExpression dL dR)+            <>  format " " (diffLabel aL aR)+            <>  format " " (diffMaybe (colon <> " ") diff bL' bR')             <>  equals             <>  " "-            <>  diffExpression eL eR--    docB = diffExpression bL bR-diffExpression l@(Let {}) r =+            <>  diff cL cR+    docs aL aR = pure (diff aL aR)+diff l@(Let {}) r =     mismatch l r-diffExpression l r@(Let {}) =+diff l r@(Let {}) =     mismatch l r-diffExpression l@(Pi {}) r@(Pi {}) =+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-            <>  lparen-            <>  format " " docA-            <>  colon-            <>  " "-            <>  format mempty docB-            <>  rparen+                    forall_+                <>  lparen+                <>  format " " docA+                <>  colon+                <>  " "+                <>  format mempty docB+                <>  rparen           where             docA = diffLabel aL aR -            docB = diffExpression bL bR+            docB = diff bL bR -    docs aL aR = pure (diffExpression aL aR)-diffExpression l@(Pi {}) r =+    docs aL aR = pure (diff aL aR)+diff l@(Pi {}) r =     mismatch l r-diffExpression l r@(Pi {}) =+diff l r@(Pi {}) =     mismatch l r-diffExpression l r =+diff (Assert aL) (Assert aR) =+    align+        (  "  " <> keyword "assert"+        <> hardline <> colon <> " " <> diff aL aR+        )+diff l@(Assert {}) r =+    mismatch l r+diff l r@(Assert {}) =+    mismatch l r+diff l r =     diffAnnotatedExpression l r -diffAnnotatedExpression :: (Eq a, Pretty a) => Expr s a -> Expr s a -> Diff+diffAnnotatedExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff diffAnnotatedExpression (Merge aL bL cL) (Merge aR bR cR) = align doc   where     doc =   keyword "merge"         <>  " "-        <>  format " " (diffImportExpression aL aR)-        <>  format " " (diffImportExpression bL bR)+        <>  format " " (diffWithExpression aL aR)+        <>  format " " (diffWithExpression bL bR)         <>  diffMaybe (colon <> " ") diffApplicationExpression cL cR diffAnnotatedExpression l@(Merge {}) r =     mismatch l r diffAnnotatedExpression l r@(Merge {}) =     mismatch l r+diffAnnotatedExpression (ToMap aL bL) (ToMap aR bR) = align doc+  where+    doc =   keyword "toMap"+        <>  " "+        <>  format " " (diffWithExpression aL aR)+        <>  diffMaybe (colon <> " ") diffApplicationExpression bL bR+diffAnnotatedExpression l@(ToMap {}) r =+    mismatch l r+diffAnnotatedExpression l r@(ToMap {}) =+    mismatch l r+diffAnnotatedExpression (ShowConstructor aL) (ShowConstructor aR) = align doc+  where+    doc =   keyword "showConstructor"+        <>  " "+        <>  format " " (diffWithExpression aL aR)+diffAnnotatedExpression l@(ShowConstructor {}) r =+    mismatch l r+diffAnnotatedExpression l r@(ShowConstructor {}) =+    mismatch l r diffAnnotatedExpression (ListLit aL@(Just _) bL) (ListLit aR bR) = align doc   where     doc =   format " " (diffList bL bR)-        <>  format " " (diffMaybe (colon <> " ") (diffApplicationExpression `on` App List) aL aR)+        <>  format " " (diffMaybe (colon <> " ") diffApplicationExpression aL aR) diffAnnotatedExpression (ListLit aL bL) (ListLit aR@(Just _) bR) = align doc   where     doc =   format " " (diffList bL bR)-        <>  format " " (diffMaybe (colon <> " ") (diffApplicationExpression `on` App List) aL aR)-diffAnnotatedExpression (OptionalLit aL bL) (OptionalLit aR bR) =-    align doc-  where-    doc =   lbracket-        <>  " "-        <>  format " " (diffMaybe mempty diffExpression bL bR)-        <>  rbracket-        <>  " "-        <>  colon-        <>  " "-        <>  diffApplicationExpression (App Optional aL) (App Optional aR)-diffAnnotatedExpression l@(OptionalLit {}) r =-    mismatch l r-diffAnnotatedExpression l r@(OptionalLit {}) =-    mismatch l r+        <>  format " " (diffMaybe (colon <> " ") diffApplicationExpression aL aR) diffAnnotatedExpression l@(Annot {}) r@(Annot {}) =     enclosed' "  " (colon <> " ") (docs l r)   where@@ -801,7 +822,7 @@       where         doc = diffOperatorExpression aL aR     docs aL aR =-        diffExpression aL aR :| []+        diff aL aR :| [] diffAnnotatedExpression l@(Annot {}) r =     mismatch l r diffAnnotatedExpression l r@(Annot {}) =@@ -809,17 +830,47 @@ diffAnnotatedExpression l r =     diffOperatorExpression l r -diffOperatorExpression :: (Eq a, Pretty a) => Expr s a -> Expr s a -> Diff-diffOperatorExpression = diffOrExpression+{- Whitespace in diffs of operator expressions: -diffOrExpression :: (Eq a, Pretty a) => Expr s a -> Expr s a -> Diff+All indentation (whether pretty-printing or diffing) is a multiple of two+spaces, so if the operator is one character long (like ?) then the diff pads+the left margin to two space:++    ␣␣e₀+    ?␣e₁++... but if the operator is two characters long (like ||) then the diff pads+the left margin to four spaces:++     ␣␣␣␣e₀+     ||␣␣e₁+-}+diffOperatorExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff+diffOperatorExpression = diffImportAltExpression++diffImportAltExpression :: (Pretty a, Eq a) => Expr Void a -> Expr Void a -> Diff+diffImportAltExpression l@(ImportAlt {}) r@(ImportAlt {}) =+    enclosed' "  " (operator "?" <> " ") (docs l r)+  where+    docs (ImportAlt aL bL) (ImportAlt aR bR) =+        Data.List.NonEmpty.cons (diffOrExpression aL aR) (docs bL bR)+    docs aL aR =+        pure (diffOrExpression aL aR)+diffImportAltExpression l@(ImportAlt {}) r =+    mismatch l r+diffImportAltExpression l r@(ImportAlt {}) =+    mismatch l r+diffImportAltExpression l r =+    diffOrExpression l r++diffOrExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff diffOrExpression l@(BoolOr {}) r@(BoolOr {}) =     enclosed' "    " (operator "||" <> "  ") (docs l r)   where     docs (BoolOr aL bL) (BoolOr aR bR) =-        Data.List.NonEmpty.cons (diffTextAppendExpression aL aR) (docs bL bR)+        Data.List.NonEmpty.cons (diffPlusExpression aL aR) (docs bL bR)     docs aL aR =-        pure (diffTextAppendExpression aL aR)+        pure (diffPlusExpression aL aR) diffOrExpression l@(BoolOr {}) r =     mismatch l r diffOrExpression l r@(BoolOr {}) =@@ -827,14 +878,14 @@ diffOrExpression l r =     diffPlusExpression l r -diffPlusExpression :: (Eq a, Pretty a) => Expr s a -> Expr s a -> Diff+diffPlusExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff diffPlusExpression l@(NaturalPlus {}) r@(NaturalPlus {}) =     enclosed' "  " (operator "+" <> " ") (docs l r)   where     docs (NaturalPlus aL bL) (NaturalPlus aR bR) =-        Data.List.NonEmpty.cons (diffListAppendExpression aL aR) (docs bL bR)+        Data.List.NonEmpty.cons (diffTextAppendExpression aL aR) (docs bL bR)     docs aL aR =-        pure (diffListAppendExpression aL aR)+        pure (diffTextAppendExpression aL aR) diffPlusExpression l@(NaturalPlus {}) r =     mismatch l r diffPlusExpression l r@(NaturalPlus {}) =@@ -842,14 +893,14 @@ diffPlusExpression l r =     diffTextAppendExpression l r -diffTextAppendExpression :: (Eq a, Pretty a) => Expr s a -> Expr s a -> Diff+diffTextAppendExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff diffTextAppendExpression l@(TextAppend {}) r@(TextAppend {}) =     enclosed' "    " (operator "++" <> "  ") (docs l r)   where     docs (TextAppend aL bL) (TextAppend aR bR) =-        Data.List.NonEmpty.cons (diffPlusExpression aL aR) (docs bL bR)+        Data.List.NonEmpty.cons (diffListAppendExpression aL aR) (docs bL bR)     docs aL aR =-        pure (diffPlusExpression aL aR)+        pure (diffListAppendExpression aL aR) diffTextAppendExpression l@(TextAppend {}) r =     mismatch l r diffTextAppendExpression l r@(TextAppend {}) =@@ -857,7 +908,7 @@ diffTextAppendExpression l r =     diffListAppendExpression l r -diffListAppendExpression :: (Eq a, Pretty a) => Expr s a -> Expr s a -> Diff+diffListAppendExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff diffListAppendExpression l@(ListAppend {}) r@(ListAppend {}) =     enclosed' "  " (operator "#" <> " ") (docs l r)   where@@ -872,7 +923,7 @@ diffListAppendExpression l r =     diffAndExpression l r -diffAndExpression :: (Eq a, Pretty a) => Expr s a -> Expr s a -> Diff+diffAndExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff diffAndExpression l@(BoolAnd {}) r@(BoolAnd {}) =     enclosed' "    " (operator "&&" <> "  ") (docs l r)   where@@ -887,11 +938,11 @@ diffAndExpression l r =     diffCombineExpression l r -diffCombineExpression :: (Eq a, Pretty a) => Expr s a -> Expr s a -> Diff+diffCombineExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff diffCombineExpression l@(Combine {}) r@(Combine {}) =     enclosed' "  " (operator "∧" <> " ") (docs l r)   where-    docs (Combine aL bL) (Combine aR bR) =+    docs (Combine _ _ aL bL) (Combine _ _ aR bR) =         Data.List.NonEmpty.cons (diffPreferExpression aL aR) (docs bL bR)     docs aL aR =         pure (diffPreferExpression aL aR)@@ -902,11 +953,11 @@ diffCombineExpression l r =     diffPreferExpression l r -diffPreferExpression :: (Eq a, Pretty a) => Expr s a -> Expr s a -> Diff+diffPreferExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff diffPreferExpression l@(Prefer {}) r@(Prefer {}) =     enclosed' "  " (operator "⫽" <> " ") (docs l r)   where-    docs (Prefer aL bL) (Prefer aR bR) =+    docs (Prefer _ _ aL bL) (Prefer _ _ aR bR) =         Data.List.NonEmpty.cons (diffCombineTypesExpression aL aR) (docs bL bR)     docs aL aR =         pure (diffCombineTypesExpression aL aR)@@ -917,11 +968,11 @@ diffPreferExpression l r =     diffCombineTypesExpression l r -diffCombineTypesExpression :: (Eq a, Pretty a) => Expr s a -> Expr s a -> Diff+diffCombineTypesExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff diffCombineTypesExpression l@(CombineTypes {}) r@(CombineTypes {}) =     enclosed' "  " (operator "*" <> " ") (docs l r)   where-    docs (CombineTypes aL bL) (CombineTypes aR bR) =+    docs (CombineTypes _ aL bL) (CombineTypes _ aR bR) =         Data.List.NonEmpty.cons (diffTimesExpression aL aR) (docs bL bR)     docs aL aR =         pure (diffTimesExpression aL aR)@@ -932,7 +983,7 @@ diffCombineTypesExpression l r =     diffTimesExpression l r -diffTimesExpression :: (Eq a, Pretty a) => Expr s a -> Expr s a -> Diff+diffTimesExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff diffTimesExpression l@(NaturalTimes {}) r@(NaturalTimes {}) =     enclosed' "  " (operator "*" <> " ") (docs l r)   where@@ -947,7 +998,7 @@ diffTimesExpression l r =     diffEqualExpression l r -diffEqualExpression :: (Eq a, Pretty a) => Expr s a -> Expr s a -> Diff+diffEqualExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff diffEqualExpression l@(BoolEQ {}) r@(BoolEQ {}) =     enclosed' "    " (operator "==" <> "  ") (docs l r)   where@@ -962,49 +1013,99 @@ diffEqualExpression l r =     diffNotEqualExpression l r -diffNotEqualExpression :: (Eq a, Pretty a) => Expr s a -> Expr s a -> Diff+diffNotEqualExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff diffNotEqualExpression l@(BoolNE {}) r@(BoolNE {}) =     enclosed' "    " (operator "!=" <> "  ") (docs l r)   where     docs (BoolNE aL bL) (BoolNE aR bR) =-        Data.List.NonEmpty.cons (diffApplicationExpression aL aR) (docs bL bR)+        Data.List.NonEmpty.cons (diffEquivalentExpression aL aR) (docs bL bR)     docs aL aR =-        pure (diffApplicationExpression aL aR)+        pure (diffEquivalentExpression aL aR) diffNotEqualExpression l@(BoolNE {}) r =     mismatch l r diffNotEqualExpression l r@(BoolNE {}) =     mismatch l r diffNotEqualExpression l r =+    diffEquivalentExpression l r++diffEquivalentExpression+    :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff+diffEquivalentExpression l@(Equivalent {}) r@(Equivalent {}) =+    enclosed' "  " (operator "≡" <> " ") (docs l r)+  where+    docs (Equivalent _ aL bL) (Equivalent _ aR bR) =+        Data.List.NonEmpty.cons (diffApplicationExpression aL aR) (docs bL bR)+    docs aL aR =+        pure (diffApplicationExpression aL aR)+diffEquivalentExpression l@(Equivalent {}) r =+    mismatch l r+diffEquivalentExpression l r@(Equivalent {}) =+    mismatch l r+diffEquivalentExpression l r =     diffApplicationExpression l r -diffApplicationExpression :: (Eq a, Pretty a) => Expr s a -> Expr s a -> Diff+diffApplicationExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff diffApplicationExpression l@(App {}) r@(App {}) =     enclosed' mempty mempty (Data.List.NonEmpty.reverse (docs l r))   where     docs (App aL bL) (App aR bR) =-        Data.List.NonEmpty.cons (diffImportExpression bL bR) (docs aL aR)+        Data.List.NonEmpty.cons (diffWithExpression bL bR) (docs aL aR)     docs (Some aL) (Some aR) =-        diffImportExpression aL aR :| [ builtin "Some" ]+        diffWithExpression aL aR :| [ builtin "Some" ]     docs aL aR@(Some {}) =         pure (mismatch aL aR)     docs aL@(Some {}) aR =         pure (mismatch aL aR)     docs aL aR =-        pure (diffImportExpression aL aR)+        pure (diffWithExpression aL aR) diffApplicationExpression l@(App {}) r =     mismatch l r diffApplicationExpression l r@(App {}) =     mismatch l r diffApplicationExpression (Some l) (Some r) =-    enclosed' mempty mempty (builtin "Some" :| [ diffImportExpression l r ])+    enclosed' mempty mempty (builtin "Some" :| [ diffWithExpression l r ]) diffApplicationExpression l@(Some {}) r =     mismatch l r diffApplicationExpression l r@(Some {}) =     mismatch l r diffApplicationExpression l r =+    diffWithExpression l r++diffWithExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff+diffWithExpression (With eL ksL vL) (With eR ksR vR) =+    align+        (   format " " (diffImportExpression eL eR)+        <>  "with "+        <>  align+            (   format " " (diffPath (fmap toText ksL) (fmap toText ksR))+            <>  "= "+            <>  diffOperatorExpression vL vR+            )+        )+  where+    toText  WithQuestion  = "?"+    toText (WithLabel k ) = k++    diffPath (kL :| []) (kR :| []) =+        diffLabel kL kR+    diffPath (kL₀ :| kL₁ : ksL') (kR₀ :| kR₁ : ksR') =+            format "" (diffLabel kL₀ kR₀)+        <>  dot+        <>  diffPath (kL₁ :| ksL') (kR₁ :| ksR')+    diffPath (kL :| []) (kR₀ :| kR₁ : ksR') =+            format "" (diffLabel kL kR₀)+        <>  plus (foldMap (\k -> dot <> token (Internal.prettyLabel k)) (kR₁ :| ksR'))+    diffPath (kL₀ :| kL₁ : ksL') (kR :| []) =+            format "" (diffLabel kL₀ kR)+        <>  minus (foldMap (\k -> dot <> token (Internal.prettyLabel k)) (kL₁ :| ksL'))+diffWithExpression l r@With{} =+    mismatch l r+diffWithExpression l@With{} r =+    mismatch l r+diffWithExpression l r =     diffImportExpression l r -diffImportExpression :: (Eq a, Pretty a) => Expr s a -> Expr s a -> Diff+diffImportExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff diffImportExpression (Embed l) (Embed r) =     diffPretty l r diffImportExpression l@(Embed {}) r =@@ -1012,18 +1113,28 @@ diffImportExpression l r@(Embed {}) =     mismatch l r diffImportExpression l r =+    diffRecordCompletionExpression l r++diffRecordCompletionExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff+diffRecordCompletionExpression (RecordCompletion aL bL) (RecordCompletion aR bR) =+       diffSelectorExpression aL aR <> "::" <> diffSelectorExpression bL bR+diffRecordCompletionExpression l@(RecordCompletion {}) r =+    mismatch l r+diffRecordCompletionExpression l r@(RecordCompletion {}) =+    mismatch l r+diffRecordCompletionExpression l r =     diffSelectorExpression l r -diffSelectorExpression :: (Eq a, Pretty a) => Expr s a -> Expr s a -> Diff+diffSelectorExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff diffSelectorExpression l@(Field {}) r@(Field {}) =     enclosed' "  " (dot <> " ") (Data.List.NonEmpty.reverse (docs l r))   where-    docs (Field aL 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)     docs (Project aL (Right bL)) (Project aR (Right bR)) =-        Data.List.NonEmpty.cons (diffExpression bL bR) (docs aL aR)+        Data.List.NonEmpty.cons (diff bL bR) (docs aL aR)     docs aL aR =         pure (diffPrimitiveExpression aL aR) diffSelectorExpression l@(Field {}) r =@@ -1033,12 +1144,12 @@ 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)     docs (Project aL (Right bL)) (Project aR (Right bR)) =-        Data.List.NonEmpty.cons (diffExpression bL bR) (docs aL aR)+        Data.List.NonEmpty.cons (diff bL bR) (docs aL aR)     docs aL aR =         pure (diffPrimitiveExpression aL aR) diffSelectorExpression l@(Project {}) r =@@ -1048,7 +1159,7 @@ diffSelectorExpression l r =     diffPrimitiveExpression l r -diffPrimitiveExpression :: (Eq a, Pretty a) => Expr s a -> Expr s a -> Diff+diffPrimitiveExpression :: (Eq a, Pretty a) => Expr Void a -> Expr Void a -> Diff diffPrimitiveExpression (Var aL) (Var aR) =     diffVar aL aR diffPrimitiveExpression l@(Var {}) r =@@ -1067,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 =@@ -1115,12 +1238,30 @@     mismatch l r diffPrimitiveExpression l r@NaturalShow =     mismatch l r+diffPrimitiveExpression NaturalSubtract NaturalSubtract =+    "…"+diffPrimitiveExpression l@NaturalSubtract r =+    mismatch l r+diffPrimitiveExpression l r@NaturalSubtract =+    mismatch l r diffPrimitiveExpression Integer Integer =     "…" diffPrimitiveExpression l@Integer r =     mismatch l r diffPrimitiveExpression l r@Integer =     mismatch l r+diffPrimitiveExpression IntegerClamp IntegerClamp =+    "…"+diffPrimitiveExpression l@IntegerClamp r =+    mismatch l r+diffPrimitiveExpression l r@IntegerClamp =+    mismatch l r+diffPrimitiveExpression IntegerNegate IntegerNegate =+    "…"+diffPrimitiveExpression l@IntegerNegate r =+    mismatch l r+diffPrimitiveExpression l r@IntegerNegate =+    mismatch l r diffPrimitiveExpression IntegerShow IntegerShow =     "…" diffPrimitiveExpression l@IntegerShow r =@@ -1151,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 =@@ -1166,10 +1349,6 @@ diffPrimitiveExpression (ListLit Nothing bL) (ListLit Nothing bR) = align doc   where     doc = format " " (diffList bL bR)-diffPrimitiveExpression l@(ListLit {}) r =-    mismatch l r-diffPrimitiveExpression l r@(ListLit {}) =-    mismatch l r diffPrimitiveExpression ListBuild ListBuild =     "…" diffPrimitiveExpression l@ListBuild r =@@ -1224,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 =@@ -1266,6 +1433,24 @@     mismatch l r diffPrimitiveExpression l r@(TextLit {}) =     mismatch l r+diffPrimitiveExpression (DateLiteral l) (DateLiteral r) =+    diffDateLiteral l r+diffPrimitiveExpression l@(DateLiteral {}) r =+    mismatch l r+diffPrimitiveExpression l r@(DateLiteral {}) =+    mismatch l r+diffPrimitiveExpression (TimeLiteral tL pL) (TimeLiteral tR pR) =+    diffTimeLiteral tL pL tR pR+diffPrimitiveExpression l@(TimeLiteral {}) r =+    mismatch l r+diffPrimitiveExpression l r@(TimeLiteral {}) =+    mismatch l r+diffPrimitiveExpression (TimeZoneLiteral l) (TimeZoneLiteral r) =+    diffTimeZoneLiteral l r+diffPrimitiveExpression l@(TimeZoneLiteral {}) r =+    mismatch l r+diffPrimitiveExpression l r@(TimeZoneLiteral {}) =+    mismatch l r diffPrimitiveExpression (Record aL) (Record aR) =     diffRecord aL aR diffPrimitiveExpression l@(Record {}) r =@@ -1284,15 +1469,9 @@     mismatch l r diffPrimitiveExpression l r@(Union {}) =     mismatch l r-diffPrimitiveExpression (UnionLit aL bL cL) (UnionLit aR bR cR) =-    diffUnionLit aL aR bL bR cL cR-diffPrimitiveExpression l@(UnionLit {}) r =-    mismatch l r-diffPrimitiveExpression l r@(UnionLit {}) =-    mismatch l r diffPrimitiveExpression aL aR =     if same doc     then ignore     else align ("( " <> doc <> hardline <> ")")   where-    doc = diffExpression aL aR+    doc = diff aL aR
+ src/Dhall/DirectoryTree.hs view
@@ -0,0 +1,515 @@+{-# LANGUAGE CPP               #-}+{-# LANGUAGE OverloadedLists   #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards   #-}+{-# LANGUAGE TupleSections     #-}+{-# LANGUAGE ViewPatterns      #-}++{-# OPTIONS_GHC -Wno-orphans #-}++-- | Implementation of the @dhall to-directory-tree@ subcommand+module Dhall.DirectoryTree+    ( -- * Filesystem+      toDirectoryTree+    , FilesystemError(..)++      -- * Low-level types and functions+    , module Dhall.DirectoryTree.Types+    , decodeDirectoryTree+    , directoryTreeType+    ) where++import Control.Applicative       (empty)+import Control.Exception         (Exception)+import Control.Monad             (unless, when)+import Data.Either.Validation    (Validation (..))+import Data.Functor.Identity     (Identity (..))+import Data.Maybe                (fromMaybe, isJust)+import Data.Sequence             (Seq)+import Data.Text                 (Text)+import Data.Void                 (Void)+import Dhall.DirectoryTree.Types+import Dhall.Marshal.Decode      (Decoder (..), Expector)+import Dhall.Src                 (Src)+import Dhall.Syntax+    ( Chunks (..)+    , Const (..)+    , Expr (..)+    , RecordField (..)+    , Var (..)+    )+import System.FilePath           ((</>))+import System.PosixCompat.Types  (FileMode, GroupID, UserID)++import qualified Control.Exception           as Exception+import qualified Data.ByteString             as ByteString+import qualified Data.Foldable               as Foldable+import qualified Data.Text                   as Text+import qualified Data.Text.IO                as Text.IO+import qualified Dhall.Core                  as Core+import qualified Dhall.Map                   as Map+import qualified Dhall.Marshal.Decode        as Decode+import qualified Dhall.Pretty+import qualified Dhall.TypeCheck             as TypeCheck+import qualified Dhall.Util                  as Util+import qualified Prettyprinter               as Pretty+import qualified Prettyprinter.Render.String as Pretty+import qualified System.Directory            as Directory+import qualified System.FilePath             as FilePath+#ifdef mingw32_HOST_OS+import System.IO.Error           (illegalOperationErrorType, mkIOError)+#else+import qualified System.Posix.User           as Posix+#endif+import qualified System.PosixCompat.Files    as Posix++{-| Attempt to transform a Dhall record into a directory tree where:++    * Records are translated into directories++    * @Map@s are also translated into directories++    * @Text@ values or fields are translated into files++    * @Optional@ values are omitted if @None@++    * There is a more advanced way to construct directory trees using a fixpoint+      encoding. See the documentation below on that.++    For example, the following Dhall record:++    > { dir = { `hello.txt` = "Hello\n" }+    > , `goodbye.txt`= Some "Goodbye\n"+    > , `missing.txt` = None Text+    > }++    ... should translate to this directory tree:++    > $ tree result+    > result+    > ├── dir+    > │   └── hello.txt+    > └── goodbye.txt+    >+    > $ cat result/dir/hello.txt+    > Hello+    >+    > $ cat result/goodbye.txt+    > Goodbye++    Use this in conjunction with the Prelude's support for rendering JSON/YAML+    in "pure Dhall" so that you can generate files containing JSON. For example:++    > let JSON =+    >       https://prelude.dhall-lang.org/v12.0.0/JSON/package.dhall sha256:843783d29e60b558c2de431ce1206ce34bdfde375fcf06de8ec5bf77092fdef7+    >+    > in  { `example.json` =+    >         JSON.render (JSON.array [ JSON.number 1.0, JSON.bool True ])+    >     , `example.yaml` =+    >         JSON.renderYAML+    >           (JSON.object (toMap { foo = JSON.string "Hello", bar = JSON.null }))+    >     }++    ... which would generate:++    > $ cat result/example.json+    > [ 1.0, true ]+    >+    > $ cat result/example.yaml+    > ! "bar": null+    > ! "foo": "Hello"++    /Advanced construction of directory trees/++    In addition to the ways described above using "simple" Dhall values to+    construct the directory tree there is one based on a fixpoint encoding. It+    works by passing a value of the following type to the interpreter:++    > let User = < UserId : Natural | UserName : Text >+    >+    > let Group = < GroupId : Natural | GroupName : Text >+    >+    > let Access =+    >       { execute : Optional Bool+    >       , read : Optional Bool+    >       , write : Optional Bool+    >       }+    >+    > let Mode =+    >       { user : Optional Access+    >       , group : Optional Access+    >       , other : Optional Access+    >       }+    >+    > let Entry =+    >       \(content : Type) ->+    >         { name : Text+    >         , content : content+    >         , user : Optional User+    >         , group : Optional Group+    >         , mode : Optional Mode+    >         }+    >+    > in  forall (tree : Type) ->+    >     forall  ( make+    >             : { directory : Entry (List tree) -> tree+    >               , file : Entry Text -> tree+    >               }+    >             ) ->+    >       List tree++    The fact that the metadata for filesystem entries is modeled after the POSIX+    permission model comes with the unfortunate downside that it might not apply+    to other systems: There, changes to the metadata (user, group, permissions)+    might be a no-op and __no warning will be issued__.+    This is a leaking abstraction of the+    [unix-compat](https://hackage.haskell.org/package/unix-compat) package used+    internally.++    __NOTE__: This utility does not take care of type-checking and normalizing+    the provided expression. This will raise a `FilesystemError` exception or a+    `Dhall.Marshal.Decode.DhallErrors` exception upon encountering an expression+    that cannot be converted as-is.+-}+toDirectoryTree+    :: Bool -- ^ Whether to allow path separators in file names or not+    -> FilePath+    -> Expr Void Void+    -> IO ()+toDirectoryTree allowSeparators path expression = case expression of+    RecordLit keyValues ->+        Map.unorderedTraverseWithKey_ process $ recordFieldValue <$> keyValues++    ListLit (Just (App List (Record [ ("mapKey", recordFieldValue -> Text), ("mapValue", _) ]))) [] ->+        Directory.createDirectoryIfMissing allowSeparators path++    ListLit _ records+        | not (null records)+        , Just keyValues <- extract (Foldable.toList records) ->+            Foldable.traverse_ (uncurry process) keyValues++    TextLit (Chunks [] text) ->+        Text.IO.writeFile path text++    Some value ->+        toDirectoryTree allowSeparators path value++    App (Field (Union _) _) value -> do+        toDirectoryTree allowSeparators path value++    App None _ ->+        return ()++    -- If this pattern matches we assume the user wants to use the fixpoint+    -- approach, hence we typecheck it and output error messages like we would+    -- do for every other Dhall program.+    Lam _ _ (Lam _ _ _) -> do+        entries <- decodeDirectoryTree expression++        processFilesystemEntryList allowSeparators path entries++    _ ->+        die+  where+    extract [] =+        return []++    extract (RecordLit [ ("mapKey", recordFieldValue -> TextLit (Chunks [] key))+                       , ("mapValue", recordFieldValue -> value)] : records) =+        fmap ((key, value) :) (extract records)++    extract _ =+        empty++    process key value = do+        when (not allowSeparators && Text.isInfixOf (Text.pack [ FilePath.pathSeparator ]) key) $+            die++        Directory.createDirectoryIfMissing allowSeparators path++        toDirectoryTree allowSeparators (path </> Text.unpack key) value++    die = Exception.throwIO FilesystemError{..}+      where+        unexpectedExpression = expression++-- | Decode a fixpoint directory tree from a Dhall expression.+decodeDirectoryTree :: Expr s Void -> IO (Seq FilesystemEntry)+decodeDirectoryTree (Core.alphaNormalize . Core.denote -> expression@(Lam _ _ (Lam _ _ body))) = do+    expected' <- case directoryTreeType of+        Success x -> return x+        Failure e -> Exception.throwIO e++    _ <- Core.throws $ TypeCheck.typeOf $ Annot expression expected'++    case Decode.extract decoder body of+        Success x -> return x+        Failure e -> Exception.throwIO e+    where+        decoder :: Decoder (Seq FilesystemEntry)+        decoder = Decode.auto+decodeDirectoryTree expr = Exception.throwIO $ FilesystemError $ Core.denote expr++-- | The type of a fixpoint directory tree expression.+directoryTreeType :: Expector (Expr Src Void)+directoryTreeType = Pi Nothing "tree" (Const Type)+    <$> (Pi Nothing "make" <$> makeType <*> pure (App List (Var (V "tree" 0))))++-- | The type of make part of a fixpoint directory tree expression.+makeType :: Expector (Expr Src Void)+makeType = Record . Map.fromList <$> sequenceA+    [ makeConstructor "directory" (Decode.auto :: Decoder DirectoryEntry)+    , makeConstructor "file" (Decode.auto :: Decoder TextFileEntry)+    , makeConstructor "binary-file" (Decode.auto :: Decoder BinaryFileEntry)+    ]+    where+        makeConstructor :: Text -> Decoder b -> Expector (Text, RecordField Src Void)+        makeConstructor name dec = (name,) . Core.makeRecordField+            <$> (Pi Nothing "_" <$> expected dec <*> pure (Var (V "tree" 0)))++-- | Resolve a `User` to a numerical id.+getUser :: User -> IO UserID+getUser (UserId uid) = return uid+getUser (UserName name) =+#ifdef mingw32_HOST_OS+    ioError $ mkIOError illegalOperationErrorType x Nothing Nothing+    where x = "System.Posix.User.getUserEntryForName: not supported"+#else+    Posix.userID <$> Posix.getUserEntryForName name+#endif++-- | Resolve a `Group` to a numerical id.+getGroup :: Group -> IO GroupID+getGroup (GroupId gid) = return gid+getGroup (GroupName name) =+#ifdef mingw32_HOST_OS+    ioError $ mkIOError illegalOperationErrorType x Nothing Nothing+    where x = "System.Posix.User.getGroupEntryForName: not supported"+#else+    Posix.groupID <$> Posix.getGroupEntryForName name+#endif++-- | Process a `FilesystemEntry`. Writes the content to disk and apply the+-- metadata to the newly created item.+processFilesystemEntry :: Bool -> FilePath -> FilesystemEntry -> IO ()+processFilesystemEntry allowSeparators path (DirectoryEntry entry) =+    processEntryWith path entry $ \path' content -> do+        Directory.createDirectoryIfMissing allowSeparators path'+        processFilesystemEntryList allowSeparators path' content+processFilesystemEntry allowSeparators path (BinaryFileEntry entry) =+    processEntryWith path entry $ \path' content -> do+        when allowSeparators $ do+            Directory.createDirectoryIfMissing True (FilePath.takeDirectory path')+        ByteString.writeFile path' content+processFilesystemEntry allowSeparators path (TextFileEntry entry) =+    processEntryWith path entry $ \path' content -> do+        when allowSeparators $ do+            Directory.createDirectoryIfMissing True (FilePath.takeDirectory path')+        Text.IO.writeFile path' content++-- | A helper function used by 'processFilesystemEntry'.+processEntryWith+    :: FilePath+    -> Entry a+    -> (FilePath -> a -> IO ())+    -> IO ()+processEntryWith path entry f = do+    let path' = path </> entryName entry+    when (hasMetadata entry && not isMetadataSupported) $+        Exception.throwIO (MetadataUnsupportedError path')+    f path' (entryContent entry)+    -- It is important that we write the metadata after we wrote the content of+    -- the file as we might lock ourself out by changing ownership or+    -- permissions.+    applyMetadata entry path'++-- | Process a list of `FilesystemEntry`s.+processFilesystemEntryList :: Bool -> FilePath -> Seq FilesystemEntry -> IO ()+processFilesystemEntryList allowSeparators path = Foldable.traverse_+    (processFilesystemEntry allowSeparators path)++-- | Does this entry have some metadata set?+hasMetadata :: Entry a -> Bool+hasMetadata entry+    =  isJust (entryUser entry)+    || isJust (entryGroup entry)+    || maybe False hasMode (entryMode entry)+    where+        hasMode :: Mode Maybe -> Bool+        hasMode mode+            =  maybe False hasAccess (modeUser mode)+            || maybe False hasAccess (modeGroup mode)+            || maybe False hasAccess (modeOther mode)++        hasAccess :: Access Maybe -> Bool+        hasAccess access+            =  isJust (accessExecute access)+            || isJust (accessRead access)+            || isJust (accessWrite access)++-- | Set the metadata of an object referenced by a path.+applyMetadata :: Entry a -> FilePath -> IO ()+applyMetadata entry fp = do+    s <- Posix.getFileStatus fp+    let user = Posix.fileOwner s+        group = Posix.fileGroup s+        mode = fileModeToMode $ Posix.fileMode s++    user' <- getUser $ fromMaybe (UserId user) (entryUser entry)+    group' <- getGroup $ fromMaybe (GroupId group) (entryGroup entry)+    unless ((user', group') == (user, group)) $+        Posix.setOwnerAndGroup fp user' group'++    let mode' = maybe mode (updateModeWith mode) (entryMode entry)+    unless (mode' == mode) $+        setFileMode fp $ modeToFileMode mode'++-- | Calculate the new `Mode` from the current mode and the changes specified by+-- the user.+updateModeWith :: Mode Identity -> Mode Maybe -> Mode Identity+updateModeWith x y = Mode+    { modeUser = combine modeUser modeUser+    , modeGroup = combine modeGroup modeGroup+    , modeOther = combine modeOther modeOther+    }+    where+        combine f g = maybe (f x) (Identity . updateAccessWith (runIdentity $ f x)) (g y)++-- | Calculate the new `Access` from the current permissions and the changes+-- specified by the user.+updateAccessWith :: Access Identity -> Access Maybe -> Access Identity+updateAccessWith x y = Access+    { accessExecute = combine accessExecute accessExecute+    , accessRead = combine accessRead accessRead+    , accessWrite = combine accessWrite accessWrite+    }+    where+        combine f g = maybe (f x) Identity (g y)++-- | Convert a filesystem mode given as a bitmask (`FileMode`) to an ADT+-- (`Mode`).+fileModeToMode :: FileMode -> Mode Identity+fileModeToMode mode = Mode+    { modeUser = Identity $ Access+        { accessExecute = Identity $ mode `hasFileMode` Posix.ownerExecuteMode+        , accessRead = Identity $ mode `hasFileMode` Posix.ownerReadMode+        , accessWrite = Identity $ mode `hasFileMode` Posix.ownerReadMode+        }+    , modeGroup = Identity $ Access+        { accessExecute = Identity $ mode `hasFileMode` Posix.groupExecuteMode+        , accessRead = Identity $ mode `hasFileMode` Posix.groupReadMode+        , accessWrite = Identity $ mode `hasFileMode` Posix.groupReadMode+        }+    , modeOther = Identity $ Access+        { accessExecute = Identity $ mode `hasFileMode` Posix.otherExecuteMode+        , accessRead = Identity $ mode `hasFileMode` Posix.otherReadMode+        , accessWrite = Identity $ mode `hasFileMode` Posix.otherReadMode+        }+    }++-- | Convert a filesystem mode given as an ADT (`Mode`) to a bitmask+-- (`FileMode`).+modeToFileMode :: Mode Identity -> FileMode+modeToFileMode mode = foldr Posix.unionFileModes Posix.nullFileMode $+    [ Posix.ownerExecuteMode | runIdentity $ accessExecute (runIdentity $ modeUser  mode) ] <>+    [ Posix.ownerReadMode    | runIdentity $ accessRead    (runIdentity $ modeUser  mode) ] <>+    [ Posix.ownerWriteMode   | runIdentity $ accessWrite   (runIdentity $ modeUser  mode) ] <>+    [ Posix.groupExecuteMode | runIdentity $ accessExecute (runIdentity $ modeGroup mode) ] <>+    [ Posix.groupReadMode    | runIdentity $ accessRead    (runIdentity $ modeGroup mode) ] <>+    [ Posix.groupWriteMode   | runIdentity $ accessWrite   (runIdentity $ modeGroup mode) ] <>+    [ Posix.otherExecuteMode | runIdentity $ accessExecute (runIdentity $ modeOther mode) ] <>+    [ Posix.otherReadMode    | runIdentity $ accessRead    (runIdentity $ modeOther mode) ] <>+    [ Posix.otherWriteMode   | runIdentity $ accessWrite   (runIdentity $ modeOther mode) ]++-- | Check whether the second `FileMode` is contained in the first one.+hasFileMode :: FileMode -> FileMode -> Bool+hasFileMode mode x = (mode `Posix.intersectFileModes` x) == x++{- | This error indicates that you supplied an invalid Dhall expression to the+     `toDirectoryTree` function.  The Dhall expression could not be translated+     to a directory tree.+-}+newtype FilesystemError =+    FilesystemError { unexpectedExpression :: Expr Void Void }++instance Exception FilesystemError++instance Show FilesystemError where+    show FilesystemError{..} =+        Pretty.renderString (Dhall.Pretty.layout message)+      where+        message =+          Util._ERROR <> ": Not a valid directory tree expression                             \n\\+          \                                                                                   \n\\+          \Explanation: Only a subset of Dhall expressions can be converted to a directory    \n\\+          \tree.  Specifically, record literals or maps can be converted to directories,      \n\\+          \❰Text❱ literals can be converted to files, and ❰Optional❱ values are included if   \n\\+          \❰Some❱ and omitted if ❰None❱.  Values of union types can also be converted if      \n\\+          \they are an alternative which has a non-nullary constructor whose argument is of   \n\\+          \an otherwise convertible type.  Furthermore, there is a more advanced approach to  \n\\+          \constructing a directory tree utilizing a fixpoint encoding. Consult the upstream  \n\\+          \documentation of the `toDirectoryTree` function in the Dhall.Directory module for  \n\\+          \further information on that.                                                       \n\\+          \No other type of value can be translated to a directory tree.                      \n\\+          \                                                                                   \n\\+          \For example, this is a valid expression that can be translated to a directory      \n\\+          \tree:                                                                              \n\\+          \                                                                                   \n\\+          \                                                                                   \n\\+          \    ┌──────────────────────────────────┐                                           \n\\+          \    │ { `example.json` = \"[1, true]\" } │                                         \n\\+          \    └──────────────────────────────────┘                                           \n\\+          \                                                                                   \n\\+          \                                                                                   \n\\+          \In contrast, the following expression is not allowed due to containing a           \n\\+          \❰Natural❱ field, which cannot be translated in this way:                           \n\\+          \                                                                                   \n\\+          \                                                                                   \n\\+          \    ┌───────────────────────┐                                                      \n\\+          \    │ { `example.txt` = 1 } │                                                      \n\\+          \    └───────────────────────┘                                                      \n\\+          \                                                                                   \n\\+          \                                                                                   \n\\+          \Note that key names cannot contain path separators:                                \n\\+          \                                                                                   \n\\+          \                                                                                   \n\\+          \    ┌─────────────────────────────────────┐                                        \n\\+          \    │ { `directory/example.txt` = \"ABC\" } │ Invalid: Key contains a forward slash\n\\+          \    └─────────────────────────────────────┘                                        \n\\+          \                                                                                   \n\\+          \                                                                                   \n\\+          \Instead, you need to refactor the expression to use nested records instead:        \n\\+          \                                                                                   \n\\+          \                                                                                   \n\\+          \    ┌───────────────────────────────────────────┐                                  \n\\+          \    │ { directory = { `example.txt` = \"ABC\" } } │                                \n\\+          \    └───────────────────────────────────────────┘                                  \n\\+          \                                                                                   \n\\+          \                                                                                   \n\\+          \You tried to translate the following expression to a directory tree:               \n\\+          \                                                                                   \n\\+          \" <> Util.insert unexpectedExpression <> "\n\\+          \                                                                                   \n\\+          \... which is not an expression that can be translated to a directory tree.         \n"++{- | This error indicates that you want to set some metadata for a file or+     directory, but that operation is not supported  on your platform.+-}+newtype MetadataUnsupportedError =+    MetadataUnsupportedError { metadataForPath :: FilePath }++instance Exception MetadataUnsupportedError++instance Show MetadataUnsupportedError where+    show MetadataUnsupportedError{..} =+        Pretty.renderString (Dhall.Pretty.layout message)+      where+        message =+          Util._ERROR <> ": Setting metadata is not supported on this platform.               \n\\+          \                                                                                   \n\\+          \Explanation: Your Dhall expression indicates that you intend to set some metadata  \n\\+          \like ownership or permissions for the following file or directory:                 \n\\+          \                                                                                   \n\\+          \" <> Pretty.pretty metadataForPath <> "\n\\+          \                                                                                   \n\\+          \... which is not supported on your platform.                                       \n"
+ src/Dhall/DirectoryTree/Types.hs view
@@ -0,0 +1,267 @@+{-# LANGUAGE CPP                #-}+{-# LANGUAGE DeriveGeneric      #-}+{-# LANGUAGE FlexibleInstances  #-}+{-# LANGUAGE LambdaCase         #-}+{-# LANGUAGE OverloadedStrings  #-}+{-# LANGUAGE PatternSynonyms    #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TypeApplications   #-}+{-# LANGUAGE ViewPatterns       #-}++{-# OPTIONS_GHC -Wno-orphans #-}++-- | Types used by the implementation of the @to-directory-tree@ subcommand+module Dhall.DirectoryTree.Types+    ( FilesystemEntry(DirectoryEntry, BinaryFileEntry, TextFileEntry, FileEntry)+    , DirectoryEntry+    , FileEntry+    , BinaryFileEntry+    , TextFileEntry+    , Entry(..)+    , User(..)+    , Group(..)+    , Mode(..)+    , Access(..)++    , setFileMode+    , prettyFileMode++    , isMetadataSupported+    ) where++import Data.ByteString          (ByteString)+import Data.Functor.Identity    (Identity (..))+import Data.Sequence            (Seq)+import Data.Text                (Text)+import Dhall.Marshal.Decode+    ( Decoder (..)+    , FromDhall (..)+    , Generic+    , InputNormalizer+    , InterpretOptions (..)+    )+import Dhall.Syntax             (Expr (..), FieldSelection (..), Var (..))+import System.PosixCompat.Types (GroupID, UserID)++import qualified Data.Text                as Text+import qualified Dhall.Marshal.Decode     as Decode+import qualified System.PosixCompat.Files as Posix++#ifdef mingw32_HOST_OS+import Control.Monad            (unless)+import Data.Word                (Word32)+import System.IO                (hPutStrLn, stderr)+import System.PosixCompat.Types (CMode)++import qualified Unsafe.Coerce++type FileMode = CMode+#else+import System.PosixCompat.Types (FileMode)++import qualified System.PosixCompat.Types as Posix+#endif++pattern Make :: Text -> Expr s a -> Expr s a+pattern Make label entry <- App (Field (Var (V "_" 0)) (fieldSelectionLabel -> label)) entry++-- | A directory in the filesystem.+type DirectoryEntry = Entry (Seq FilesystemEntry)++-- | A file in the filesystem.+{-# DEPRECATED FileEntry "`FileEntry` is deprecated and will be removed eventually. Please use `TextFileEntry` instead." #-}+type FileEntry = Entry Text++-- | A binary file in the filesystem.+type BinaryFileEntry = Entry ByteString++-- | A text file in the filesystem.+type TextFileEntry = Entry Text++-- | A filesystem entry.+data FilesystemEntry+    = DirectoryEntry (Entry (Seq FilesystemEntry))+    | BinaryFileEntry BinaryFileEntry+    | TextFileEntry TextFileEntry+    deriving (Eq, Generic, Ord, Show)++pattern FileEntry :: Entry Text -> FilesystemEntry+pattern FileEntry entry = TextFileEntry entry++instance FromDhall FilesystemEntry where+    autoWith normalizer = Decoder+        { expected = pure $ Var (V "tree" 0)+        , extract = \case+            Make "directory" entry ->+                DirectoryEntry <$> extract (autoWith normalizer) entry+            Make "file" entry ->+                TextFileEntry <$> extract (autoWith normalizer) entry+            Make "binary-file" entry ->+                BinaryFileEntry <$> extract (autoWith normalizer) entry+            expr -> Decode.typeError (expected (Decode.autoWith normalizer :: Decoder FilesystemEntry)) expr+        }++-- | A generic filesystem entry. This type holds the metadata that apply to all+-- entries. It is parametric over the content of such an entry.+data Entry a = Entry+    { entryName :: String+    , entryContent :: a+    , entryUser :: Maybe User+    , entryGroup :: Maybe Group+    , entryMode :: Maybe (Mode Maybe)+    }+    deriving (Eq, Generic, Ord, Show)++instance FromDhall a => FromDhall (Entry a) where+    autoWith = Decode.genericAutoWithInputNormalizer Decode.defaultInterpretOptions+        { fieldModifier = Text.toLower . Text.drop (Text.length "entry")+        }++-- | A user identified either by id or name.+data User+    = UserId UserID+    | UserName String+    deriving (Eq, Generic, Ord, Show)++instance FromDhall User++#ifdef mingw32_HOST_OS+instance FromDhall UserID where+    autoWith normalizer = Unsafe.Coerce.unsafeCoerce <$> autoWith @Word32 normalizer+#else+instance FromDhall Posix.CUid where+    autoWith normalizer = Posix.CUid <$> autoWith normalizer+#endif++-- | A group identified either by id or name.+data Group+    = GroupId GroupID+    | GroupName String+    deriving (Eq, Generic, Ord, Show)++instance FromDhall Group++#ifdef mingw32_HOST_OS+instance FromDhall GroupID where+    autoWith normalizer = Unsafe.Coerce.unsafeCoerce <$> autoWith @Word32 normalizer+#else+instance FromDhall Posix.CGid where+    autoWith normalizer = Posix.CGid <$> autoWith normalizer+#endif++-- | A filesystem mode. See chmod(1).+-- The parameter is meant to be instantiated by either `Identity` or `Maybe`+-- depending on the completeness of the information:+--  * For data read from the filesystem it will be `Identity`.+--  * For user-supplied data it will be `Maybe` as we want to be able to set+--    only specific bits.+data Mode f = Mode+    { modeUser :: f (Access f)+    , modeGroup :: f (Access f)+    , modeOther :: f (Access f)+    }+    deriving Generic++deriving instance Eq (Mode Identity)+deriving instance Eq (Mode Maybe)+deriving instance Ord (Mode Identity)+deriving instance Ord (Mode Maybe)+deriving instance Show (Mode Identity)+deriving instance Show (Mode Maybe)++instance FromDhall (Mode Identity) where+    autoWith = modeDecoder++instance FromDhall (Mode Maybe) where+    autoWith = modeDecoder++modeDecoder :: FromDhall (f (Access f)) => InputNormalizer -> Decoder (Mode f)+modeDecoder = Decode.genericAutoWithInputNormalizer Decode.defaultInterpretOptions+    { fieldModifier = Text.toLower . Text.drop (Text.length "mode")+    }++-- | The permissions for a subject (user/group/other).+data Access f = Access+    { accessExecute :: f Bool+    , accessRead :: f Bool+    , accessWrite :: f Bool+    }+    deriving Generic++deriving instance Eq (Access Identity)+deriving instance Eq (Access Maybe)+deriving instance Ord (Access Identity)+deriving instance Ord (Access Maybe)+deriving instance Show (Access Identity)+deriving instance Show (Access Maybe)++instance FromDhall (Access Identity) where+    autoWith = accessDecoder++instance FromDhall (Access Maybe) where+    autoWith = accessDecoder++accessDecoder :: FromDhall (f Bool) => InputNormalizer -> Decoder (Access f)+accessDecoder = Decode.genericAutoWithInputNormalizer Decode.defaultInterpretOptions+    { fieldModifier = Text.toLower . Text.drop (Text.length "access")+    }++++-- | A wrapper around `Posix.setFileMode`. On Windows, it does check the+-- resulting file mode of the file/directory and emits a warning if it doesn't+-- match the desired file mode. On all other OS it is identical to+-- `Posix.setFileMode` as it is assumed to work correctly.+setFileMode :: FilePath -> FileMode -> IO ()+#ifdef mingw32_HOST_OS+setFileMode fp mode = do+    Posix.setFileMode fp mode+    mode' <- Posix.fileMode <$> Posix.getFileStatus fp+    unless (mode' == mode) $ hPutStrLn stderr $+        "Warning: Setting file mode did not succeed for " <> fp <> "\n" <>+        "    Expected: " <> prettyFileMode mode <> "\n" <>+        "    Actual:   " <> prettyFileMode mode'+#else+setFileMode fp mode = Posix.setFileMode fp mode+#endif++-- | Pretty-print a `FileMode`. The format is similar to the one ls(1):+-- It is display as three blocks of three characters. The first block are the+-- permissions of the user, the second one are the ones of the group and the+-- third one the ones of other subjects. A @r@ denotes that the file or+-- directory is readable by the subject, a @w@ denotes that it is writable and+-- an @x@ denotes that it is executable. Unset permissions are represented by+-- @-@.+prettyFileMode :: FileMode -> String+prettyFileMode mode = userPP <> groupPP <> otherPP+    where+        userPP :: String+        userPP =+            isBitSet 'r' Posix.ownerReadMode <>+            isBitSet 'w' Posix.ownerWriteMode <>+            isBitSet 'x' Posix.ownerExecuteMode++        groupPP :: String+        groupPP =+            isBitSet 'r' Posix.groupReadMode <>+            isBitSet 'w' Posix.groupWriteMode <>+            isBitSet 'x' Posix.groupExecuteMode++        otherPP :: String+        otherPP =+            isBitSet 'r' Posix.otherReadMode <>+            isBitSet 'w' Posix.otherWriteMode <>+            isBitSet 'x' Posix.otherExecuteMode++        isBitSet :: Char -> FileMode -> String+        isBitSet c mask = if mask `Posix.intersectFileModes` mode /= Posix.nullFileMode+            then [c]+            else "-"++-- | Is setting metadata supported on this platform or not.+isMetadataSupported :: Bool+#ifdef mingw32_HOST_OS+isMetadataSupported = False+#else+isMetadataSupported = True+#endif
src/Dhall/Eval.hs view
@@ -1,946 +1,1567 @@-{-# LANGUAGE-  BangPatterns,-  CPP,-  LambdaCase,-  OverloadedStrings,-  PatternSynonyms,-  RankNTypes,-  ScopedTypeVariables,-  TupleSections,-  ViewPatterns-  #-}--{-# OPTIONS_GHC-  -O-  -fno-warn-name-shadowing-  -fno-warn-unused-matches-  #-}--{-|-Eval-apply environment machine with conversion checking and quoting to normal-forms. Fairly similar to GHCI's STG machine algorithmically, but much simpler,-with no known call optimization or environment trimming.--Potential optimizations without changing Expr:-  - In conversion checking, get non-shadowing variables not by linear-    Env-walking, but by keeping track of Env size, and generating names which-    are known to be illegal as source-level names (to rule out shadowing).-  - Use HashMap Text chunks for large let-definitions blocks. "Large" vs "Small"-    is fairly cheap to determine at evaluation time.--Potential optimizations with changing Expr:-  - Use Int in Var instead of Integer. Overflow is practically impossible.-  - Use actual full de Bruijn indices in Var instead of Text counting indices. Then, we'd-    switch to full de Bruijn levels in Val as well, and use proper constant time non-shadowing-    name generation.---}--module Dhall.Eval (-    Env(..)-  , Names(..)-  , Closure(..)-  , VChunks(..)-  , Val(..)-  , Void-  , inst-  , eval-  , conv-  , convEmpty-  , quote-  , nf-  , nfEmpty-  , Dhall.Eval.alphaNormalize-  ) where--#if MIN_VERSION_base(4,8,0)-#else-import Control.Applicative (Applicative(..), (<$>))-#endif--import Data.Foldable (foldr', foldl', toList)-import Data.List.NonEmpty (NonEmpty(..), cons)-import Data.Semigroup (Semigroup(..))-import Data.Sequence (Seq)-import Data.Text (Text)--import Dhall.Core (-    Expr(..)-  , Binding(..)-  , Chunks(..)-  , Const(..)-  , Import-  , Var(..)-  , denote-  )---- import Control.Exception (throw)--- import Dhall.Import.Types (InternalError)-import Dhall.Map (Map)-import Dhall.Set (Set)-import GHC.Natural (Natural)-import Unsafe.Coerce (unsafeCoerce)--import qualified Data.Char-import qualified Data.List.NonEmpty-import qualified Data.Sequence-import qualified Data.Text-import qualified Dhall.Binary-import qualified Dhall.Map-import qualified Dhall.Set-import qualified Text.Printf--------------------------------------------------------------------------------------------------------data Env a =-    Empty-  | Skip !(Env a) {-# unpack #-} !Text-  | Extend !(Env a) {-# unpack #-} !Text (Val a)--data Void--coeExprVoid :: Expr Void a -> Expr s a-coeExprVoid = unsafeCoerce-{-# inline coeExprVoid #-}--errorMsg :: String-errorMsg = unlines-  [ _ERROR <> ": Compiler bug                                                        "-  , "                                                                                "-  , "An ill-typed expression was encountered during normalization.                   "-  , "Explanation: This error message means that there is a bug in the Dhall compiler."-  , "You didn't do anything wrong, but if you would like to see this problem fixed   "-  , "then you should report the bug at:                                              "-  , "                                                                                "-  , "https://github.com/dhall-lang/dhall-haskell/issues                              "-  ]-  where-    _ERROR :: String-    _ERROR = "\ESC[1;31mError\ESC[0m"---data Closure a = Cl !Text !(Env a) !(Expr Void a)-data VChunks a = VChunks ![(Text, Val a)] !Text--instance Semigroup (VChunks a) where-  VChunks xys z <> VChunks [] z' = VChunks xys (z <> z')-  VChunks xys z <> VChunks ((x', y'):xys') z' = VChunks (xys ++ (z <> x', y'):xys') z'--instance Monoid (VChunks a) where-  mempty = VChunks [] mempty--#if !(MIN_VERSION_base(4,11,0))-  mappend = (<>)-#endif--data HLamInfo a-  = Prim-  | Typed !Text (Val a)-  | NaturalFoldCl (Val a)-  | ListFoldCl (Val a)-  | OptionalFoldCl (Val a)--pattern VPrim :: (Val a -> Val a) -> Val a-pattern VPrim f = VHLam Prim f--data Val a-  = VConst !Const-  | VVar !Text !Int-  | VPrimVar-  | VApp !(Val a) !(Val a)--  | VLam (Val a) {-# unpack #-} !(Closure a)-  | VHLam !(HLamInfo a) !(Val a -> Val a)--  | VPi  (Val a) {-# unpack #-} !(Closure a)-  | VHPi !Text (Val a) !(Val a -> Val a)--  | VBool-  | VBoolLit !Bool-  | VBoolAnd !(Val a) !(Val a)-  | VBoolOr !(Val a) !(Val a)-  | VBoolEQ !(Val a) !(Val a)-  | VBoolNE !(Val a) !(Val a)-  | VBoolIf !(Val a) !(Val a) !(Val a)--  | VNatural-  | VNaturalLit !Natural-  | VNaturalFold !(Val a) !(Val a) !(Val a) !(Val a)-  | VNaturalBuild !(Val a)-  | VNaturalIsZero !(Val a)-  | VNaturalEven !(Val a)-  | VNaturalOdd !(Val a)-  | VNaturalToInteger !(Val a)-  | VNaturalShow !(Val a)-  | VNaturalPlus !(Val a) !(Val a)-  | VNaturalTimes !(Val a) !(Val a)--  | VInteger-  | VIntegerLit !Integer-  | VIntegerShow !(Val a)-  | VIntegerToDouble !(Val a)--  | VDouble-  | VDoubleLit !Double-  | VDoubleShow !(Val a)--  | VText-  | VTextLit !(VChunks a)-  | VTextAppend !(Val a) !(Val a)-  | VTextShow !(Val a)--  | VList !(Val a)-  | VListLit !(Maybe (Val a)) !(Seq (Val a))-  | VListAppend !(Val a) !(Val a)-  | VListBuild   (Val a) !(Val a)-  | VListFold    (Val a) !(Val a) !(Val a) !(Val a) !(Val a)-  | VListLength  (Val a) !(Val a)-  | VListHead    (Val a) !(Val a)-  | VListLast    (Val a) !(Val a)-  | VListIndexed (Val a) !(Val a)-  | VListReverse (Val a) !(Val a)--  | VOptional (Val a)-  | VSome (Val a)-  | VNone (Val a)-  | 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)))-  | VUnionLit !Text !(Val a) !(Map Text (Maybe (Val a)))-  | VCombine !(Val a) !(Val a)-  | VCombineTypes !(Val a) !(Val a)-  | VPrefer !(Val a) !(Val a)-  | VMerge !(Val a) !(Val a) !(Maybe (Val a))-  | VField !(Val a) !Text-  | VInject !(Map Text (Maybe (Val a))) !Text !(Maybe (Val a))-  | VProject !(Val a) !(Either (Set Text) (Val a))-  | VEmbed a--vFun :: Val a -> Val a -> Val a-vFun a b = VHPi "_" a (\_ -> b)-{-# inline vFun #-}---- Evaluation-------------------------------------------------------------------------------------------------------textShow :: Text -> Text-textShow text = "\"" <> Data.Text.concatMap f text <> "\""-  where-    f '"'  = "\\\""-    f '$'  = "\\u0024"-    f '\\' = "\\\\"-    f '\b' = "\\b"-    f '\n' = "\\n"-    f '\r' = "\\r"-    f '\t' = "\\t"-    f '\f' = "\\f"-    f c | c <= '\x1F' = Data.Text.pack (Text.Printf.printf "\\u%04x" (Data.Char.ord c))-        | otherwise   = Data.Text.singleton c--countName :: Text -> Env a -> Int-countName x = go (0 :: Int) where-  go !acc Empty             = acc-  go  acc (Skip env x'    ) = go (if x == x' then acc + 1 else acc) env-  go  acc (Extend env x' _) = go (if x == x' then acc + 1 else acc) env--inst :: Eq a => Closure a -> Val a -> Val a-inst (Cl x env t) !u = eval (Extend env x u) t-{-# inline inst #-}---- Out-of-env variables have negative de Bruijn levels.-vVar :: Env a -> Var -> Val a-vVar env (V x (fromInteger -> i :: Int)) = go env i where-  go (Extend env x' v) i-    | x == x'   = if i == 0 then v else go env (i - 1)-    | otherwise = go env i-  go (Skip env x') i-    | x == x'   = if i == 0 then VVar x (countName x env) else go env (i - 1)-    | otherwise = go env i-  go Empty i = VVar x (0 - i - 1)--vApp :: Eq a => Val a -> Val a -> Val a-vApp !t !u = case t of-  VLam _ t    -> inst t u-  VHLam _ t   -> t u-  t           -> VApp t u-{-# inline vApp #-}--vCombine :: Val a -> Val a -> Val a-vCombine t u = case (t, u) of-  (VRecordLit m, u) | null m    -> u-  (t, VRecordLit m) | null m    -> t-  (VRecordLit m, VRecordLit m') -> VRecordLit (Dhall.Map.sort (Dhall.Map.unionWith vCombine m m'))-  (t, u)                        -> VCombine t u--vCombineTypes :: Val a -> Val a -> Val a-vCombineTypes t u = case (t, u) of-  (VRecord m, u) | null m -> u-  (t, VRecord m) | null m -> t-  (VRecord m, VRecord m') -> VRecord (Dhall.Map.sort (Dhall.Map.unionWith vCombineTypes m m'))-  (t, u)                  -> VCombineTypes t u--vListAppend :: Val a -> Val a -> Val a-vListAppend t u = case (t, u) of-  (VListLit _ xs, u) | null xs   -> u-  (t, VListLit _ ys) | null ys   -> t-  (VListLit t xs, VListLit _ ys) -> VListLit t (xs <> ys)-  (t, u)                         -> VListAppend t u-{-# inline vListAppend #-}--vNaturalPlus :: Val a -> Val a -> Val a-vNaturalPlus t u = case (t, u) of-  (VNaturalLit 0, u            ) -> u-  (t,             VNaturalLit 0) -> t-  (VNaturalLit m, VNaturalLit n) -> VNaturalLit (m + n)-  (t,             u            ) -> VNaturalPlus t u-{-# inline vNaturalPlus #-}--eval :: forall a. Eq a => Env a -> Expr Void a -> Val a-eval !env t =-  let-    evalE :: Expr Void a -> Val a-    evalE = eval env-    {-# inline evalE #-}--    evalChunks :: Chunks Void a -> VChunks a-    evalChunks (Chunks xys z) =-      foldr' (\(x, t) vcs ->-                case evalE t of-                  VTextLit vcs' -> VChunks [] x <> vcs' <> vcs-                  t             -> VChunks [(x, t)] mempty <> vcs)-            (VChunks [] z)-            xys-    {-# inline evalChunks #-}--  in case t of-    Const k          -> VConst k-    Var v            -> vVar env v-    Lam x a t        -> VLam (evalE a) (Cl x env t)-    Pi x a b         -> VPi (evalE a) (Cl x env b)-    App t u          -> vApp (evalE t) (evalE u)-    Let (b :| bs) t  -> go env (b:bs) where-                          go !env []     = eval env t-                          go  env (b:bs) = go (Extend env (variable b)-                                                          (eval env (value b))) bs-    Annot t _        -> evalE t--    Bool             -> VBool-    BoolLit b        -> VBoolLit b-    BoolAnd t u      -> case (evalE t, evalE u) of-                          (VBoolLit True, u)    -> u-                          (VBoolLit False, u)   -> VBoolLit False-                          (t, VBoolLit True)    -> t-                          (t, VBoolLit False)   -> VBoolLit False-                          (t, u) | conv env t u -> t-                          (t, u)                -> VBoolAnd t u-    BoolOr t u       -> case (evalE t, evalE u) of-                          (VBoolLit False, u)   -> u-                          (VBoolLit True, u)    -> VBoolLit True-                          (t, VBoolLit False)   -> t-                          (t, VBoolLit True)    -> VBoolLit True-                          (t, u) | conv env t u -> t-                          (t, u)                -> VBoolOr t u-    BoolEQ t u       -> case (evalE t, evalE u) of-                          (VBoolLit True, u)    -> u-                          (t, VBoolLit True)    -> t-                          (t, u) | conv env t u -> VBoolLit True-                          (t, u)                -> VBoolEQ t u-    BoolNE t u       -> case (evalE t, evalE u) of-                          (VBoolLit False, u)   -> u-                          (t, VBoolLit False)   -> t-                          (t, u) | conv env t u -> VBoolLit False-                          (t, u)                -> VBoolNE t u-    BoolIf b t f     -> case (evalE b, evalE t, evalE f) of-                          (VBoolLit True,  t, f)   -> t-                          (VBoolLit False, t, f)   -> f-                          (b, VBoolLit True, VBoolLit False) -> b-                          (b, t, f) | conv env t f -> t-                          (b, t, f)                -> VBoolIf b t f--    Natural          -> VNatural-    NaturalLit n     -> VNaturalLit n-    NaturalFold      -> VPrim $ \case-                          VNaturalLit n ->-                            VHLam (Typed "natural" (VConst Type)) $ \natural ->-                            VHLam (Typed "succ" (vFun natural natural)) $ \succ ->-                            VHLam (Typed "zero" natural) $ \zero ->-                              let go !acc 0 = acc-                                  go  acc n = go (vApp succ acc) (n - 1)-                              in go zero (fromIntegral n :: Integer)-                          n ->-                            VHLam (NaturalFoldCl n) $ \natural -> VPrim $ \succ -> VPrim $ \zero ->-                              VNaturalFold n natural succ zero-    NaturalBuild     -> VPrim $ \case-                          VHLam (NaturalFoldCl x) _ -> x-                          VPrimVar -> VNaturalBuild VPrimVar-                          t        ->-                             t `vApp` VNatural-                               `vApp` VHLam (Typed "n" VNatural) (\n -> vNaturalPlus n (VNaturalLit 1))-                               `vApp` VNaturalLit 0--    NaturalIsZero    -> VPrim $ \case VNaturalLit n -> VBoolLit (n == 0)-                                      n             -> VNaturalIsZero n-    NaturalEven      -> VPrim $ \case VNaturalLit n -> VBoolLit (even n)-                                      n             -> VNaturalEven n-    NaturalOdd       -> VPrim $ \case VNaturalLit n -> VBoolLit (odd n)-                                      n             -> VNaturalOdd n-    NaturalToInteger -> VPrim $ \case VNaturalLit n -> VIntegerLit (fromIntegral n)-                                      n             -> VNaturalToInteger n-    NaturalShow      -> VPrim $ \case VNaturalLit n -> VTextLit (VChunks [] (Data.Text.pack (show n)))-                                      n             -> VNaturalShow n-    NaturalPlus t u  -> vNaturalPlus (evalE t) (evalE u)-    NaturalTimes t u -> case (evalE t, evalE u) of-                          (VNaturalLit 1, u            ) -> u-                          (t,             VNaturalLit 1) -> t-                          (VNaturalLit 0, u            ) -> VNaturalLit 0-                          (t,             VNaturalLit 0) -> VNaturalLit 0-                          (VNaturalLit m, VNaturalLit n) -> VNaturalLit (m * n)-                          (t,             u            ) -> VNaturalTimes t u--    Integer          -> VInteger-    IntegerLit n     -> VIntegerLit n-    IntegerShow      -> VPrim $ \case-                          VIntegerLit n-                            | 0 <= n    -> VTextLit (VChunks [] (Data.Text.pack ('+':show n)))-                            | otherwise -> VTextLit (VChunks [] (Data.Text.pack (show n)))-                          n -> VIntegerShow n-    IntegerToDouble  -> VPrim $ \case VIntegerLit n -> VDoubleLit (read (show n))-                                      -- `(read . show)` is used instead of `fromInteger`-                                      -- because `read` uses the correct rounding rule-                                      n             -> VIntegerToDouble n--    Double           -> VDouble-    DoubleLit n      -> VDoubleLit n-    DoubleShow       -> VPrim $ \case VDoubleLit n -> VTextLit (VChunks [] (Data.Text.pack (show n)))-                                      n            -> VDoubleShow n--    Text             -> VText-    TextLit cs       -> case evalChunks cs of-                          VChunks [("", t)] "" -> t-                          vcs                  -> VTextLit vcs-    TextAppend t u   -> evalE (TextLit (Chunks [("", t), ("", u)] ""))-    TextShow         -> VPrim $ \case-                          VTextLit (VChunks [] x) -> VTextLit (VChunks [] (textShow x))-                          t                       -> VTextShow t--    List             -> VPrim VList-    ListLit ma ts    -> VListLit (evalE <$> ma) (evalE <$> ts)-    ListAppend t u   -> vListAppend (evalE t) (evalE u)-    ListBuild        -> VPrim $ \a -> VPrim $ \case-                          VHLam (ListFoldCl x) _ -> x-                          VPrimVar -> VListBuild a VPrimVar-                          t ->-                            t `vApp` VList a-                              `vApp` VHLam (Typed "a" a) (\x ->-                                              VHLam (Typed "as" (VList a)) (\as ->-                                                vListAppend (VListLit Nothing (pure x)) as))-                              `vApp` VListLit (Just a) mempty--    ListFold         -> VPrim $ \a -> VPrim $ \case-                          VListLit _ as ->-                            VHLam (Typed "list" (VConst Type)) $ \list ->-                            VHLam (Typed "cons" (vFun a $ vFun list list) ) $ \cons ->-                            VHLam (Typed "nil"  list) $ \nil ->-                              foldr' (\x b -> cons `vApp` x `vApp` b) nil as-                          as ->-                            VHLam (ListFoldCl as) $ \t -> VPrim $ \c -> VPrim $ \n ->-                              VListFold a as t c n--    ListLength       -> VPrim $ \ a -> VPrim $ \case-                          VListLit _ as -> VNaturalLit (fromIntegral (Data.Sequence.length as))-                          as            -> VListLength a as-    ListHead         -> VPrim $ \ a -> VPrim $ \case-                          VListLit _ as -> case Data.Sequence.viewl as of-                                             y Data.Sequence.:< _ -> VSome y-                                             _                    -> VNone a-                          as            -> VListHead a as-    ListLast         -> VPrim $ \ a -> VPrim $ \case-                          VListLit _ as -> case Data.Sequence.viewr as of-                                             _ Data.Sequence.:> t -> VSome t-                                             _                    -> VNone a-                          as            -> VListLast a as-    ListIndexed      -> VPrim $ \ a -> VPrim $ \case-                          VListLit _ as -> let-                            a' = if null as then-                                   Just (VRecord (Dhall.Map.fromList-                                                  [("index", VNatural), ("value", a)]))-                                 else-                                   Nothing-                            as' = Data.Sequence.mapWithIndex-                                    (\i t -> VRecordLit-                                      (Dhall.Map.fromList [("index", VNaturalLit (fromIntegral i)),-                                                           ("value", t)]))-                                    as-                            in VListLit a' as'-                          t -> VListIndexed a t-    ListReverse      -> VPrim $ \ ~a -> VPrim $ \case-                          VListLit t as | null as -> VListLit t (Data.Sequence.reverse as)-                          VListLit t as -> VListLit Nothing (Data.Sequence.reverse as)-                          t             -> VListReverse a t--    Optional         -> VPrim VOptional-    OptionalLit a mt -> maybe (VNone (evalE a)) (\t -> VSome (evalE t)) mt-    Some t           -> VSome (evalE t)-    None             -> VPrim $ \ ~a -> VNone a--    OptionalFold     -> VPrim $ \ ~a -> VPrim $ \case-                          VNone _ ->-                            VHLam (Typed "optional" (VConst Type)) $ \optional ->-                            VHLam (Typed "some" (vFun a optional)) $ \some ->-                            VHLam (Typed "none" optional) $ \none ->-                            none-                          VSome t ->-                            VHLam (Typed "optional" (VConst Type)) $ \optional ->-                            VHLam (Typed "some" (vFun a optional)) $ \some ->-                            VHLam (Typed "none" optional) $ \none ->-                            some `vApp` t-                          opt ->-                            VHLam (OptionalFoldCl opt) $ \o ->-                            VPrim $ \s ->-                            VPrim $ \n ->-                            VOptionalFold a opt o s n-    OptionalBuild    -> VPrim $ \ ~a -> VPrim $ \case-                          VHLam (OptionalFoldCl x) _ -> x-                          VPrimVar -> VOptionalBuild a VPrimVar-                          t -> t `vApp` VOptional a-                                 `vApp` VHLam (Typed "a" a) VSome-                                 `vApp` VNone a--    Record kts       -> VRecord (Dhall.Map.sort (evalE <$> kts))-    RecordLit kts    -> VRecordLit (Dhall.Map.sort (evalE <$> kts))-    Union kts        -> VUnion (Dhall.Map.sort ((evalE <$>) <$> kts))-    UnionLit k v kts -> VUnionLit k (evalE v) (Dhall.Map.sort ((evalE <$>) <$> kts))-    Combine t u      -> vCombine (evalE t) (evalE u)-    CombineTypes t u -> vCombineTypes (evalE t) (evalE u)-    Prefer t u       -> case (evalE t, evalE u) of-                          (VRecordLit m, u) | null m -> u-                          (t, VRecordLit m) | null m -> t-                          (VRecordLit m, VRecordLit m') ->-                             VRecordLit (Dhall.Map.sort (Dhall.Map.union m' m))-                          (t, u) -> VPrefer t u-    Merge x y ma     -> case (evalE x, evalE y, evalE <$> ma) of-                          (VRecordLit m, VUnionLit k v _, _)-                            | Just f <- Dhall.Map.lookup k m -> f `vApp` v-                            | otherwise -> error errorMsg-                          (VRecordLit m, VInject _ k mt, _)-                            | Just f  <- Dhall.Map.lookup k m -> maybe f (vApp f) mt-                            | otherwise -> error errorMsg-                          (x, y, ma) -> VMerge x y ma-    Field t k        -> case evalE t of-                          VRecordLit m-                            | Just v <- Dhall.Map.lookup k m -> v-                            | otherwise -> error errorMsg-                          VUnion m -> case Dhall.Map.lookup k m of-                            Just (Just _) -> VPrim $ \ ~u -> VInject m k (Just u)-                            Just Nothing  -> VInject m k Nothing-                            _             -> error errorMsg-                          t -> VField t k-    Project t (Left ks) ->-                        if null ks then-                          VRecordLit mempty-                        else case evalE t of-                          VRecordLit kvs-                            | Just s <- traverse (\k -> (k,) <$> Dhall.Map.lookup k kvs) (toList ks)-                              -> VRecordLit (Dhall.Map.sort (Dhall.Map.fromList s))-                            | otherwise -> error errorMsg-                          t -> VProject t (Left ks)-    Project t (Right e) ->-                        case evalE e of-                          VRecord kts ->-                            evalE (Project t (Left (Dhall.Set.fromList (Dhall.Map.keys kts))))-                          e' -> VProject (evalE t) (Right e')-    Note _ e         -> evalE e-    ImportAlt t _    -> evalE t-    Embed a          -> VEmbed a----- Conversion checking-----------------------------------------------------------------------------------eqListBy :: (a -> a -> Bool) -> [a] -> [a] -> Bool-eqListBy f = go where-  go (x:xs) (y:ys) | f x y = go xs ys-  go [] [] = True-  go _  _  = False-{-# inline eqListBy #-}--eqMapsBy :: Ord k => (v -> v -> Bool) -> Map k v -> Map k v -> Bool-eqMapsBy f mL mR = eqListBy eq (Dhall.Map.toList mL) (Dhall.Map.toList mR)-  where-    eq (kL, vL) (kR, vR) = kL == kR && f vL vR-{-# inline eqMapsBy #-}--eqMaybeBy :: (a -> a -> Bool) -> Maybe a -> Maybe a -> Bool-eqMaybeBy f = go where-  go (Just x) (Just y) = f x y-  go Nothing  Nothing  = True-  go _        _        = False-{-# inline eqMaybeBy #-}--conv :: forall a. Eq a => Env a -> Val a -> Val a -> Bool-conv !env t t' =-  let-    fresh :: Text -> (Text, Val a)-    fresh x = (x, VVar x (countName x env))-    {-# inline fresh #-}--    freshCl :: Closure a -> (Text, Val a, Closure a)-    freshCl cl@(Cl x _ _) = (x, snd (fresh x), cl)-    {-# inline freshCl #-}--    convChunks :: VChunks a -> VChunks a -> Bool-    convChunks (VChunks xys z) (VChunks xys' z') =-      eqListBy (\(x, y) (x', y') -> x == x' && conv env y y') xys xys' && z == z'-    {-# inline convChunks #-}--    convE :: Val a -> Val a -> Bool-    convE = conv env-    {-# inline convE #-}--    convSkip :: Text -> Val a -> Val a -> Bool-    convSkip x = conv (Skip env x)-    {-# inline convSkip #-}--  in case (t, t') of-    (VConst k, VConst k') -> k == k'-    (VVar x i, VVar x' i') -> x == x' && i == i'--    (VLam _ (freshCl -> (x, v, t)), VLam _ t' ) -> convSkip x (inst t v) (inst t' v)-    (VLam _ (freshCl -> (x, v, t)), VHLam _ t') -> convSkip x (inst t v) (t' v)-    (VLam _ (freshCl -> (x, v, t)), t'        ) -> convSkip x (inst t v) (vApp t' v)-    (VHLam _ t, VLam _ (freshCl -> (x, v, t'))) -> convSkip x (t v) (inst t' v)-    (VHLam _ t, VHLam _ t'                    ) -> let (x, v) = fresh "x" in convSkip x (t v) (t' v)-    (VHLam _ t, t'                            ) -> let (x, v) = fresh "x" in convSkip x (t v) (vApp t' v)--    (t, VLam _ (freshCl -> (x, v, t'))) -> convSkip x (vApp t v) (inst t' v)-    (t, VHLam _ t'  ) -> let (x, v) = fresh "x" in convSkip x (vApp t v) (t' v)--    (VApp t u, VApp t' u') -> convE t t' && convE u u'--    (VPi a b, VPi a' (freshCl -> (x, v, b'))) ->-      convE a a' && convSkip x (inst b v) (inst b' v)-    (VPi a b, VHPi (fresh -> (x, v)) a' b') ->-      convE a a' && convSkip x (inst b v) (b' v)-    (VHPi _ a b, VPi a' (freshCl -> (x, v, b'))) ->-      convE a a' && convSkip x (b v) (inst b' v)-    (VHPi _ a b, VHPi (fresh -> (x, v)) a' b') ->-      convE a a' && convSkip x (b v) (b' v)--    (VBool       , VBool            ) -> True-    (VBoolLit b  , VBoolLit b'      ) -> b == b'-    (VBoolAnd t u, VBoolAnd t' u'   ) -> convE t t' && convE u u'-    (VBoolOr  t u, VBoolOr  t' u'   ) -> convE t t' && convE u u'-    (VBoolEQ  t u, VBoolEQ  t' u'   ) -> convE t t' && convE u u'-    (VBoolNE  t u, VBoolNE  t' u'   ) -> convE t t' && convE u u'-    (VBoolIf t u v, VBoolIf t' u' v') -> convE t t' && convE u u' && convE v v'--    (VNatural, VNatural) -> True-    (VNaturalLit n, VNaturalLit n') -> n == n'-    (VNaturalFold t _ u v, VNaturalFold t' _ u' v') ->-      convE t t' && convE u u' && convE v v'--    (VNaturalBuild t     , VNaturalBuild t')     -> convE t t'-    (VNaturalIsZero t    , VNaturalIsZero t')    -> convE t t'-    (VNaturalEven t      , VNaturalEven t')      -> convE t t'-    (VNaturalOdd t       , VNaturalOdd t')       -> convE t t'-    (VNaturalToInteger t , VNaturalToInteger t') -> convE t t'-    (VNaturalShow t      , VNaturalShow t')      -> convE t t'-    (VNaturalPlus t u    , VNaturalPlus t' u')   -> convE t t' && convE u u'-    (VNaturalTimes t u   , VNaturalTimes t' u')  -> convE t t' && convE u u'--    (VInteger           , VInteger)            -> True-    (VIntegerLit t      , VIntegerLit t')      -> t == t'-    (VIntegerShow t     , VIntegerShow t')     -> convE t t'-    (VIntegerToDouble t , VIntegerToDouble t') -> convE t t'--    (VDouble       , VDouble)        -> True-    (VDoubleLit n  , VDoubleLit n')  -> Dhall.Binary.encode (DoubleLit n  :: Expr Void Import) ==-                                        Dhall.Binary.encode (DoubleLit n' :: Expr Void Import)-    (VDoubleShow t , VDoubleShow t') -> convE t t'--    (VText, VText) -> True--    (VTextLit cs     , VTextLit cs')      -> convChunks cs cs'-    (VTextAppend t u , VTextAppend t' u') -> convE t t' && convE u u'-    (VTextShow t     , VTextShow t')      -> convE t t'--    (VList a        , VList a'      ) -> convE a a'-    (VListLit _ xs  , VListLit _ xs') -> eqListBy convE (toList xs) (toList xs')--    (VListAppend t u     , VListAppend t' u'       ) -> convE t t' && convE u u'-    (VListBuild a t      , VListBuild a' t'        ) -> convE t t'-    (VListLength a t     , VListLength a' t'       ) -> convE a a' && convE t t'-    (VListHead _ t       , VListHead _ t'          ) -> convE t t'-    (VListLast _ t       , VListLast _ t'          ) -> convE t t'-    (VListIndexed _ t    , VListIndexed _ t'       ) -> convE t t'-    (VListReverse _ t    , VListReverse _ t'       ) -> convE t t'-    (VListFold a l _ t u , VListFold a' l' _ t' u' ) ->-      convE a a' && convE l l' && convE t t' && convE u u'--    (VOptional a             , VOptional a'                ) -> convE a a'-    (VSome t                 , VSome t'                    ) -> convE t t'-    (VNone _                 , VNone _                     ) -> True-    (VOptionalBuild _ t      , VOptionalBuild _ t'         ) -> convE t t'-    (VRecord m               , VRecord m'                  ) -> eqMapsBy convE m m'-    (VRecordLit m            , VRecordLit m'               ) -> eqMapsBy convE m m'-    (VUnion m                , VUnion m'                   ) -> eqMapsBy (eqMaybeBy convE) m m'-    (VUnionLit k v m         , VUnionLit k' v' m'          ) -> k == k' && convE v v' &&-                                                                  eqMapsBy (eqMaybeBy convE)  m m'-    (VCombine t u            , VCombine t' u'              ) -> convE t t' && convE u u'-    (VCombineTypes t u       , VCombineTypes t' u'         ) -> convE t t' && convE u u'-    (VPrefer  t u            , VPrefer t' u'               ) -> convE t t' && convE u u'-    (VMerge t u _            , VMerge t' u' _              ) -> convE t t' && convE u u'-    (VField t k              , VField t' k'                ) -> convE t t' && k == k'-    (VProject t (Left ks)    , VProject t' (Left ks')      ) -> convE t t' && ks == ks'-    (VProject t (Right e)    , VProject t' (Right e')      ) -> convE t t' && convE e e'-    (VInject m k mt          , VInject m' k' mt'           ) -> eqMapsBy (eqMaybeBy convE) m m'-                                                                  && k == k' && eqMaybeBy convE mt mt'-    (VEmbed a                , VEmbed a'                   ) -> a == a'-    (VOptionalFold a t _ u v , VOptionalFold a' t' _ u' v' ) ->-      convE a a' && convE t t' && convE u u' && convE v v'--    (_, _) -> False--convEmpty :: Eq a => Expr s a -> Expr t a -> Bool-convEmpty (denote -> t) (denote -> u) = conv Empty (eval Empty t) (eval Empty u)---- Quoting-------------------------------------------------------------------------------------------------------data Names-  = NEmpty-  | NBind !Names {-# unpack #-} !Text-  deriving Show--envNames :: Env a -> Names-envNames Empty = NEmpty-envNames (Skip   env x  ) = NBind (envNames env) x-envNames (Extend env x _) = NBind (envNames env) x--countName' :: Text -> Names -> Int-countName' x = go 0 where-  go !acc NEmpty         = acc-  go  acc (NBind env x') = go (if x == x' then acc + 1 else acc) env---- | Quote a value into beta-normal form.-quote :: forall a. Eq a => Names -> Val a -> Expr Void a-quote !env !t =-  let-    fresh :: Text -> (Text, Val a)-    fresh x = (x, VVar x (countName' x env))-    {-# inline fresh #-}--    freshCl :: Closure a -> (Text, Val a, Closure a)-    freshCl cl@(Cl x _ _) = (x, snd (fresh x), cl)-    {-# inline freshCl #-}--    qVar :: Text -> Int -> Expr Void a-    qVar !x !i = Var (V x (fromIntegral (countName' x env - i - 1)))-    {-# inline qVar #-}--    quoteE :: Val a -> Expr Void a-    quoteE = quote env-    {-# inline quoteE #-}--    quoteBind :: Text -> Val a -> Expr Void a-    quoteBind x = quote (NBind env x)-    {-# inline quoteBind #-}--    qApp :: Expr Void a -> Val a -> Expr Void a-    qApp t VPrimVar = t-    qApp t u        = App t (quoteE u)-    {-# inline qApp #-}--  in case t of-    VConst k                      -> Const k-    VVar x i                      -> qVar x i-    VApp t u                      -> quoteE t `qApp` u-    VLam a (freshCl -> (x, v, t)) -> Lam x (quoteE a) (quoteBind x (inst t v))-    VHLam i t                     -> case i of-                                       Typed (fresh -> (x, v)) a -> Lam x (quoteE a) (quoteBind x (t v))-                                       Prim                      -> quote env (t VPrimVar)-                                       NaturalFoldCl{}           -> quote env (t VPrimVar)-                                       ListFoldCl{}              -> quote env (t VPrimVar)-                                       OptionalFoldCl{}          -> quote env (t VPrimVar)--    VPi a (freshCl -> (x, v, b))  -> Pi x (quoteE a) (quoteBind x (inst b v))-    VHPi (fresh -> (x, v)) a b    -> Pi x (quoteE a) (quoteBind x (b v))--    VBool                         -> Bool-    VBoolLit b                    -> BoolLit b-    VBoolAnd t u                  -> BoolAnd (quoteE t) (quoteE u)-    VBoolOr t u                   -> BoolOr (quoteE t) (quoteE u)-    VBoolEQ t u                   -> BoolEQ (quoteE t) (quoteE u)-    VBoolNE t u                   -> BoolNE (quoteE t) (quoteE u)-    VBoolIf t u v                 -> BoolIf (quoteE t) (quoteE u) (quoteE v)--    VNatural                      -> Natural-    VNaturalLit n                 -> NaturalLit n-    VNaturalFold a t u v          -> NaturalFold `qApp` a `qApp` t `qApp` u `qApp` v-    VNaturalBuild t               -> NaturalBuild `qApp` t-    VNaturalIsZero t              -> NaturalIsZero `qApp` t-    VNaturalEven t                -> NaturalEven `qApp` t-    VNaturalOdd t                 -> NaturalOdd `qApp` t-    VNaturalToInteger t           -> NaturalToInteger `qApp` t-    VNaturalShow t                -> NaturalShow `qApp` t-    VNaturalPlus t u              -> NaturalPlus (quoteE t) (quoteE u)-    VNaturalTimes t u             -> NaturalTimes (quoteE t) (quoteE u)--    VInteger                      -> Integer-    VIntegerLit n                 -> IntegerLit n-    VIntegerShow t                -> IntegerShow `qApp` t-    VIntegerToDouble t            -> IntegerToDouble `qApp` t--    VDouble                       -> Double-    VDoubleLit n                  -> DoubleLit n-    VDoubleShow t                 -> DoubleShow `qApp` t--    VText                         -> Text-    VTextLit (VChunks xys z)      -> TextLit (Chunks ((quoteE <$>) <$> xys) z)-    VTextAppend t u               -> TextAppend (quoteE t) (quoteE u)-    VTextShow t                   -> TextShow `qApp` t--    VList t                       -> List `qApp` t-    VListLit ma ts                -> ListLit (quoteE <$> ma) (quoteE <$> ts)-    VListAppend t u               -> ListAppend (quoteE t) (quoteE u)-    VListBuild a t                -> ListBuild `qApp` a `qApp` t-    VListFold a l t u v           -> ListFold `qApp` a `qApp` l `qApp` t `qApp` u `qApp` v-    VListLength a t               -> ListLength `qApp` a `qApp` t-    VListHead a t                 -> ListHead `qApp` a `qApp` t-    VListLast a t                 -> ListLast `qApp` a `qApp` t-    VListIndexed a t              -> ListIndexed `qApp` a `qApp` t-    VListReverse a t              -> ListReverse `qApp` a `qApp` t--    VOptional a                   -> Optional `qApp` a-    VSome t                       -> Some (quoteE 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 (quoteE <$> m)-    VRecordLit m                  -> RecordLit (quoteE <$> m)-    VUnion m                      -> Union ((quoteE <$>) <$> m)-    VUnionLit k v m               -> UnionLit k (quoteE v) ((quoteE <$>) <$> m)-    VCombine t u                  -> Combine (quoteE t) (quoteE u)-    VCombineTypes t u             -> CombineTypes (quoteE t) (quoteE u)-    VPrefer t u                   -> Prefer (quoteE t) (quoteE u)-    VMerge t u ma                 -> Merge (quoteE t) (quoteE u) (quoteE <$> ma)-    VField t k                    -> Field (quoteE t) k-    VProject t p                  -> Project (quoteE t) (fmap quoteE p)-    VInject m k Nothing           -> Field (Union ((quoteE <$>) <$> m)) k-    VInject m k (Just t)          -> Field (Union ((quoteE <$>) <$> m)) k `qApp` t-    VEmbed a                      -> Embed a-    VPrimVar                      -> error errorMsg---- Normalization--------------------------------------------------------------------------------------------------------- | Normalize an expression in an environment of values. Any variable pointing out of---   the environment is treated as opaque free variable.-nf :: Eq a => Env a -> Expr s a -> Expr t a-nf !env = coeExprVoid . quote (envNames env) . eval env . denote---- | Normalize an expression in an empty environment.-nfEmpty :: Eq a => Expr s a -> Expr t a-nfEmpty = nf Empty---- Alpha-renaming------------------------------------------------------------------------------------- | Rename all binders to "_".-alphaNormalize :: Expr s a -> Expr s a-alphaNormalize = goEnv NEmpty where--  goVar :: Names -> Text -> Integer -> Expr s a-  goVar e topX topI = go 0 e topI where-    go !acc (NBind env x) !i-      | x == topX = if i == 0 then Var (V "_" acc) else go (acc + 1) env (i - 1)-      | otherwise = go (acc + 1) env i-    go acc NEmpty i = Var (V topX i)--  goEnv :: Names -> Expr s a -> Expr s a-  goEnv !e t = let--    go                     = goEnv e-    goBind x               = goEnv (NBind e x)-    goChunks (Chunks ts x) = Chunks ((go <$>) <$> ts) x--    in case t of-      Const k          -> Const k-      Var (V x i)      -> goVar e x i-      Lam x t u        -> Lam "_" (go t) (goBind x u)-      Pi x a b         -> Pi "_" (go a) (goBind x b)-      App t u          -> App (go t) (go u)--      Let (b :| bs) u  ->-        let Binding x a t = b--            nil = (NBind e x, Binding "_" (goEnv e <$> a) (goEnv e t) :| [])--            snoc (e, bs) (Binding x a t) =-                (NBind e x, cons (Binding "_" (goEnv e <$> a) (goEnv e t)) bs)--            (e', Data.List.NonEmpty.reverse -> bs') = foldl' snoc nil bs--        in Let bs' (goEnv e' u)--      Annot t u        -> Annot (go t) (go u)-      Bool             -> Bool-      BoolLit b        -> BoolLit b-      BoolAnd t u      -> BoolAnd (go t) (go u)-      BoolOr t u       -> BoolOr  (go t) (go u)-      BoolEQ t u       -> BoolEQ  (go t) (go u)-      BoolNE t u       -> BoolNE  (go t) (go u)-      BoolIf b t f     -> BoolIf  (go b) (go t) (go f)-      Natural          -> Natural-      NaturalLit n     -> NaturalLit n-      NaturalFold      -> NaturalFold-      NaturalBuild     -> NaturalBuild-      NaturalIsZero    -> NaturalIsZero-      NaturalEven      -> NaturalEven-      NaturalOdd       -> NaturalOdd-      NaturalToInteger -> NaturalToInteger-      NaturalShow      -> NaturalShow-      NaturalPlus t u  -> NaturalPlus  (go t) (go u)-      NaturalTimes t u -> NaturalTimes (go t) (go u)-      Integer          -> Integer-      IntegerLit n     -> IntegerLit n-      IntegerShow      -> IntegerShow-      IntegerToDouble  -> IntegerToDouble-      Double           -> Double-      DoubleLit n      -> DoubleLit n-      DoubleShow       -> DoubleShow-      Text             -> Text-      TextLit cs       -> TextLit (goChunks cs)-      TextAppend t u   -> TextAppend (go t) (go u)-      TextShow         -> TextShow-      List             -> List-      ListLit ma ts    -> ListLit (go <$> ma) (go <$> ts)-      ListAppend t u   -> ListAppend (go t) (go u)-      ListBuild        -> ListBuild-      ListFold         -> ListFold-      ListLength       -> ListLength-      ListHead         -> ListHead-      ListLast         -> ListLast-      ListIndexed      -> ListIndexed-      ListReverse      -> ListReverse-      Optional         -> Optional-      OptionalLit a mt -> OptionalLit (go a) (go <$> mt)-      Some t           -> Some (go t)-      None             -> None-      OptionalFold     -> OptionalFold-      OptionalBuild    -> OptionalBuild-      Record kts       -> Record (go <$> kts)-      RecordLit kts    -> RecordLit (go <$> kts)-      Union kts        -> Union ((go <$>) <$> kts)-      UnionLit k v kts -> UnionLit k (go v) ((go <$>) <$> kts)-      Combine t u      -> Combine (go t) (go u)-      CombineTypes t u -> CombineTypes  (go t) (go u)-      Prefer t u       -> Prefer (go t) (go u)-      Merge x y ma     -> Merge (go x) (go y) (go <$> ma)-      Field t k        -> Field (go t) k-      Project t ks     -> Project (go t) ks-      Note s e         -> Note s (go e)-      ImportAlt t u    -> ImportAlt (go t) (go u)-      Embed a          -> Embed a+{-# LANGUAGE AllowAmbiguousTypes  #-}+{-# LANGUAGE BangPatterns         #-}+{-# LANGUAGE FlexibleContexts     #-}+{-# LANGUAGE LambdaCase           #-}+{-# LANGUAGE OverloadedStrings    #-}+{-# LANGUAGE PatternSynonyms      #-}+{-# LANGUAGE RankNTypes           #-}+{-# LANGUAGE ScopedTypeVariables  #-}+{-# LANGUAGE StandaloneDeriving   #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE ViewPatterns         #-}++{-| Eval-apply environment machine with conversion checking and quoting to+    normal forms. Fairly similar to GHCI's STG machine algorithmically, but much+    simpler, with no known call optimization or environment trimming.++    Potential optimizations without changing Expr:++    * In conversion checking, get non-shadowing variables not by linear+      Env-walking, but by keeping track of Env size, and generating names which+      are known to be illegal as source-level names (to rule out shadowing).++    * Use HashMap Text chunks for large let-definitions blocks. "Large" vs+      "Small" is fairly cheap to determine at evaluation time.++    Potential optimizations with changing Expr:++    * Use actual full de Bruijn indices in Var instead of Text counting indices.+      Then, we'd switch to full de Bruijn levels in Val as well, and use proper+      constant time non-shadowing name generation.+-}++module Dhall.Eval (+    judgmentallyEqual+  , normalize+  , alphaNormalize+  , eval+  , quote+  , envNames+  , countNames+  , conv+  , toVHPi+  , Closure(..)+  , Names(..)+  , Environment(..)+  , Val(..)+  , (~>)+  , textShow+  , dateShow+  , timeShow+  , timezoneShow+  ) where++import Data.Bifunctor     (first)+import Data.ByteString    (ByteString)+import Data.Foldable      (foldr', toList)+import Data.List.NonEmpty (NonEmpty (..))+import Data.Sequence      (Seq, ViewL (..), ViewR (..))+import Data.Text          (Text)+import Data.Time          (Day, TimeOfDay (..), TimeZone)+import Data.Void          (Void)+import Dhall.Map          (Map)+import Dhall.Set          (Set)+import GHC.Natural        (Natural)+import Prelude            hiding (succ)++import Dhall.Syntax+    ( Binding (..)+    , Chunks (..)+    , Const (..)+    , DhallDouble (..)+    , Expr (..)+    , FunctionBinding (..)+    , PreferAnnotation (..)+    , RecordField (..)+    , Var (..)+    , WithComponent (..)+    )++import qualified Data.Char+import qualified Data.Sequence as Sequence+import qualified Data.Set+import qualified Data.Text     as Text+import qualified Data.Time     as Time+import qualified Dhall.Map     as Map+import qualified Dhall.Set+import qualified Dhall.Syntax  as Syntax+import qualified Text.Printf   as Printf++data Environment a+    = Empty+    | Skip   !(Environment a) {-# UNPACK #-} !Text+    | Extend !(Environment a) {-# UNPACK #-} !Text (Val a)++deriving instance (Show a, Show (Val a -> Val a)) => Show (Environment a)++errorMsg :: String+errorMsg = unlines+  [ _ERROR <> ": Compiler bug                                                        "+  , "                                                                                "+  , "An ill-typed expression was encountered during normalization.                   "+  , "Explanation: This error message means that there is a bug in the Dhall compiler."+  , "You didn't do anything wrong, but if you would like to see this problem fixed   "+  , "then you should report the bug at:                                              "+  , "                                                                                "+  , "https://github.com/dhall-lang/dhall-haskell/issues                              "+  ]+  where+    _ERROR :: String+    _ERROR = "\ESC[1;31mError\ESC[0m"+++data Closure a = Closure !Text !(Environment a) !(Expr Void a)++deriving instance (Show a, Show (Val a -> Val a)) => Show (Closure a)++data VChunks a = VChunks ![(Text, Val a)] !Text++deriving instance (Show a, Show (Val a -> Val a)) => Show (VChunks a)++instance Semigroup (VChunks a) where+  VChunks xys z <> VChunks [] z' = VChunks xys (z <> z')+  VChunks xys z <> VChunks ((x', y'):xys') z' = VChunks (xys ++ (z <> x', y'):xys') z'++instance Monoid (VChunks a) where+  mempty = VChunks [] mempty++{-| Some information is lost when `eval` converts a `Lam` or a built-in function+    from the `Expr` type to a `VHLam` of the `Val` type and `quote` needs that+    information in order to reconstruct an equivalent `Expr`.  This `HLamInfo`+    type holds that extra information necessary to perform that reconstruction+-}+data HLamInfo a+  = Prim+  -- ^ Don't store any information+  | Typed !Text (Val a)+  -- ^ Store the original name and type of the variable bound by the `Lam`+  | NaturalSubtractZero+  -- ^ The original function was a @Natural/subtract 0@.  We need to preserve+  --   this information in case the @Natural/subtract@ ends up not being fully+  --   saturated, in which case we need to recover the unsaturated built-in+  | TextReplaceEmpty+  -- ^ The original function was a @Text/replace ""@+  | TextReplaceEmptyArgument (Val a)+  -- ^ The original function was a @Text/replace "" replacement@++deriving instance (Show a, Show (Val a -> Val a)) => Show (HLamInfo a)++pattern VPrim :: (Val a -> Val a) -> Val a+pattern VPrim f = VHLam Prim f++toVHPi :: Eq a => Val a -> Maybe (Text, Val a, Val a -> Val a)+toVHPi (VPi a b@(Closure x _ _)) = Just (x, a, instantiate b)+toVHPi (VHPi x a b             ) = Just (x, a, b)+toVHPi  _                        = Nothing+{-# INLINABLE toVHPi #-}++data Val a+    = VConst !Const+    | VVar !Text !Int+    | VPrimVar+    | VApp !(Val a) !(Val a)++    | VLam (Val a) {-# UNPACK #-} !(Closure a)+    | VHLam !(HLamInfo a) !(Val a -> Val a)++    | VPi (Val a) {-# UNPACK #-} !(Closure a)+    | VHPi !Text (Val a) !(Val a -> Val a)++    | VBool+    | VBoolLit !Bool+    | VBoolAnd !(Val a) !(Val a)+    | VBoolOr !(Val a) !(Val a)+    | VBoolEQ !(Val a) !(Val a)+    | VBoolNE !(Val a) !(Val a)+    | VBoolIf !(Val a) !(Val a) !(Val a)++    | VBytes+    | VBytesLit ByteString++    | VNatural+    | VNaturalLit !Natural+    | VNaturalFold !(Val a) !(Val a) !(Val a) !(Val a)+    | VNaturalBuild !(Val a)+    | VNaturalIsZero !(Val a)+    | VNaturalEven !(Val a)+    | VNaturalOdd !(Val a)+    | VNaturalToInteger !(Val a)+    | VNaturalShow !(Val a)+    | VNaturalSubtract !(Val a) !(Val a)+    | VNaturalPlus !(Val a) !(Val a)+    | VNaturalTimes !(Val a) !(Val a)++    | VInteger+    | VIntegerLit !Integer+    | VIntegerClamp !(Val a)+    | VIntegerNegate !(Val a)+    | VIntegerShow !(Val a)+    | VIntegerToDouble !(Val a)++    | VDouble+    | VDoubleLit !DhallDouble+    | VDoubleShow !(Val a)++    | VText+    | VTextLit !(VChunks a)+    | VTextAppend !(Val a) !(Val a)+    | VTextShow !(Val a)+    | VTextReplace !(Val a) !(Val a) !(Val a)++    | VDate+    | VDateLiteral Time.Day+    | VDateShow !(Val a)+    | VTime+    | VTimeLiteral Time.TimeOfDay Word+    | VTimeShow !(Val a)+    | VTimeZone+    | VTimeZoneLiteral Time.TimeZone+    | VTimeZoneShow !(Val a)++    | VList !(Val a)+    | VListLit !(Maybe (Val a)) !(Seq (Val a))+    | VListAppend !(Val a) !(Val a)+    | VListBuild   (Val a) !(Val a)+    | VListFold    (Val a) !(Val a) !(Val a) !(Val a) !(Val a)+    | VListLength  (Val a) !(Val a)+    | VListHead    (Val a) !(Val a)+    | VListLast    (Val a) !(Val a)+    | VListIndexed (Val a) !(Val a)+    | VListReverse (Val a) !(Val a)++    | VOptional (Val a)+    | VSome (Val a)+    | VNone (Val a)+    | VRecord !(Map Text (Val a))+    | VRecordLit !(Map Text (Val a))+    | VUnion !(Map Text (Maybe (Val a)))+    | VCombine !(Maybe Text) !(Val a) !(Val a)+    | VCombineTypes !(Val a) !(Val a)+    | VPrefer !(Val a) !(Val a)+    | VMerge !(Val a) !(Val a) !(Maybe (Val a))+    | VToMap !(Val a) !(Maybe (Val a))+    | VShowConstructor !(Val a)+    | VField !(Val a) !Text+    | VInject !(Map Text (Maybe (Val a))) !Text !(Maybe (Val a))+    | VProject !(Val a) !(Either (Set Text) (Val a))+    | VAssert !(Val a)+    | VEquivalent !(Val a) !(Val a)+    | VWith !(Val a) (NonEmpty WithComponent) !(Val a)+    | VEmbed a++-- | For use with "Text.Show.Functions".+deriving instance (Show a, Show (Val a -> Val a)) => Show (Val a)++(~>) :: Val a -> Val a -> Val a+(~>) a b = VHPi "_" a (\_ -> b)+{-# INLINE (~>) #-}++infixr 5 ~>++countEnvironment :: Text -> Environment a -> Int+countEnvironment x = go (0 :: Int)+  where+    go !acc Empty             = acc+    go  acc (Skip env x'    ) = go (if x == x' then acc + 1 else acc) env+    go  acc (Extend env x' _) = go (if x == x' then acc + 1 else acc) env++instantiate :: Eq a => Closure a -> Val a -> Val a+instantiate (Closure x env t) !u = eval (Extend env x u) t+{-# INLINE instantiate #-}++-- Out-of-env variables have negative de Bruijn levels.+vVar :: Environment a -> Var -> Val a+vVar env0 (V x i0) = go env0 i0+  where+    go (Extend env x' v) i+        | x == x' =+            if i == 0 then v else go env (i - 1)+        | otherwise =+            go env i+    go (Skip env x') i+        | x == x' =+            if i == 0 then VVar x (countEnvironment x env) else go env (i - 1)+        | otherwise =+            go env i+    go Empty i =+        VVar x (negate i - 1)++vApp :: Eq a => Val a -> Val a -> Val a+vApp !t !u =+    case t of+        VLam _ t'  -> instantiate t' u+        VHLam _ t' -> t' u+        t'        -> VApp t' u+{-# INLINE vApp #-}++vPrefer :: Eq a => Environment a -> Val a -> Val a -> Val a+vPrefer env t u =+    case (t, u) of+        (VRecordLit m, u') | null m ->+            u'+        (t', VRecordLit m) | null m ->+            t'+        (VRecordLit m, VRecordLit m') ->+            VRecordLit (Map.union m' m)+        (t', u') | conv env t' u' ->+            t'+        (t', u') ->+            VPrefer t' u'+{-# INLINE vPrefer #-}++vCombine :: Maybe Text -> Val a -> Val a -> Val a+vCombine mk t u =+    case (t, u) of+        (VRecordLit m, u') | null m ->+            u'+        (t', VRecordLit m) | null m ->+            t'+        (VRecordLit m, VRecordLit m') ->+            VRecordLit (Map.unionWith (vCombine Nothing) m m')+        (t', u') ->+            VCombine mk t' u'++vCombineTypes :: Val a -> Val a -> Val a+vCombineTypes t u =+    case (t, u) of+        (VRecord m, u') | null m ->+            u'+        (t', VRecord m) | null m ->+            t'+        (VRecord m, VRecord m') ->+            VRecord (Map.unionWith vCombineTypes m m')+        (t', u') ->+            VCombineTypes t' u'++vListAppend :: Val a -> Val a -> Val a+vListAppend t u =+    case (t, u) of+        (VListLit _ xs, u') | null xs ->+            u'+        (t', VListLit _ ys) | null ys ->+            t'+        (VListLit t' xs, VListLit _ ys) ->+            VListLit t' (xs <> ys)+        (t', u') ->+            VListAppend t' u'+{-# INLINE vListAppend #-}++vNaturalPlus :: Val a -> Val a -> Val a+vNaturalPlus t u =+    case (t, u) of+        (VNaturalLit 0, u') ->+            u'+        (t', VNaturalLit 0) ->+            t'+        (VNaturalLit m, VNaturalLit n) ->+            VNaturalLit (m + n)+        (t', u') ->+            VNaturalPlus t' u'+{-# INLINE vNaturalPlus #-}++vField :: Val a -> Text -> Val a+vField t0 k = go t0+  where+    go = \case+        VUnion m -> case Map.lookup k m of+            Just (Just _) -> VPrim $ \ ~u -> VInject m k (Just u)+            Just Nothing  -> VInject m k Nothing+            _             -> error errorMsg+        VRecordLit m+            | Just v <- Map.lookup k m -> v+            | otherwise -> error errorMsg+        VProject t _ -> go t+        VPrefer (VRecordLit m) r -> case Map.lookup k m of+            Just v -> VField (VPrefer (singletonVRecordLit v) r) k+            Nothing -> go r+        VPrefer l (VRecordLit m) -> case Map.lookup k m of+            Just v -> v+            Nothing -> go l+        VCombine mk (VRecordLit m) r -> case Map.lookup k m of+            Just v -> VField (VCombine mk (singletonVRecordLit v) r) k+            Nothing -> go r+        VCombine mk l (VRecordLit m) -> case Map.lookup k m of+            Just v -> VField (VCombine mk l (singletonVRecordLit v)) k+            Nothing -> go l+        t -> VField t k++    singletonVRecordLit v = VRecordLit (Map.singleton k v)+{-# INLINE vField #-}++vTextReplace :: Text -> Val a -> Text -> VChunks a+vTextReplace needle replacement haystack = go haystack+  where+    go t+        | Text.null suffix = VChunks [] t+        | otherwise =+            let remainder = Text.drop (Text.length needle) suffix++                rest = go remainder++            in  case replacement of+                    VTextLit replacementChunks ->+                        VChunks [] prefix <> replacementChunks <> rest+                    _ ->+                        VChunks [(prefix, replacement)] "" <> rest+      where+        (prefix, suffix) = Text.breakOn needle t++vProjectByFields :: Eq a => Environment a -> Val a -> Set Text -> Val a+vProjectByFields env t ks =+    if null ks+        then VRecordLit mempty+        else case t of+            VRecordLit kvs ->+                let kvs' = Map.restrictKeys kvs (Dhall.Set.toSet ks)+                in  VRecordLit kvs'+            VProject t' _ ->+                vProjectByFields env t' ks+            VPrefer l (VRecordLit kvs) ->+                let ksSet = Dhall.Set.toSet ks++                    kvs' = Map.restrictKeys kvs ksSet++                    ks' =+                        Dhall.Set.fromSet+                            (Data.Set.difference ksSet (Map.keysSet kvs'))++                in  vPrefer env (vProjectByFields env l ks') (VRecordLit kvs')+            t' ->+                VProject t' (Left ks)++vWith :: Val a -> NonEmpty WithComponent -> Val a -> Val a+vWith (VRecordLit kvs) (WithLabel k  :| []     ) v = VRecordLit (Map.insert k  v  kvs)+vWith (VRecordLit kvs) (WithLabel k₀ :| k₁ : ks) v = VRecordLit (Map.insert k₀ e₂ kvs)+  where+    e₁ =+        case Map.lookup k₀ kvs of+            Nothing  -> VRecordLit mempty+            Just e₁' -> e₁'++    e₂ = vWith e₁ (k₁ :| ks) v+vWith (VNone _T) (WithQuestion :| _      ) _ = VNone _T+vWith (VSome  _) (WithQuestion :| []     ) v = VSome v+vWith (VSome  t) (WithQuestion :| k₁ : ks) v = VSome (vWith t (k₁ :| ks) v)+vWith e₀ ks v₀ = VWith e₀ ks v₀++eval :: forall a. Eq a => Environment a -> Expr Void a -> Val a+eval !env t0 =+    case t0 of+        Const k ->+            VConst k+        Var v ->+            vVar env v+        Lam _ (FunctionBinding { functionBindingVariable = x, functionBindingAnnotation = a }) t ->+            VLam (eval env a) (Closure x env t)+        Pi _ x a b ->+            VPi (eval env a) (Closure x env b)+        App t u ->+            vApp (eval env t) (eval env u)+        Let (Binding _ x _ _mA _ a) b ->+            let !env' = Extend env x (eval env a)+            in  eval env' b+        Annot t _ ->+            eval env t+        Bool ->+            VBool+        BoolLit b ->+            VBoolLit b+        BoolAnd t u ->+            case (eval env t, eval env u) of+                (VBoolLit True, u')       -> u'+                (VBoolLit False, _)       -> VBoolLit False+                (t', VBoolLit True)       -> t'+                (_ , VBoolLit False)      -> VBoolLit False+                (t', u') | conv env t' u' -> t'+                (t', u')                  -> VBoolAnd t' u'+        BoolOr t u ->+            case (eval env t, eval env u) of+                (VBoolLit False, u')      -> u'+                (VBoolLit True, _)        -> VBoolLit True+                (t', VBoolLit False)      -> t'+                (_ , VBoolLit True)       -> VBoolLit True+                (t', u') | conv env t' u' -> t'+                (t', u')                  -> VBoolOr t' u'+        BoolEQ t u ->+            case (eval env t, eval env u) of+                (VBoolLit True, u')       -> u'+                (t', VBoolLit True)       -> t'+                (t', u') | conv env t' u' -> VBoolLit True+                (t', u')                  -> VBoolEQ t' u'+        BoolNE t u ->+            case (eval env t, eval env u) of+                (VBoolLit False, u')      -> u'+                (t', VBoolLit False)      -> t'+                (t', u') | conv env t' u' -> VBoolLit False+                (t', u')                  -> VBoolNE t' u'+        BoolIf b t f ->+            case (eval env b, eval env t, eval env f) of+                (VBoolLit True,  t', _ )            -> t'+                (VBoolLit False, _ , f')            -> f'+                (b', VBoolLit True, VBoolLit False) -> b'+                (_, t', f') | conv env t' f'        -> t'+                (b', t', f')                        -> VBoolIf b' t' f'+        Bytes ->+            VBytes+        BytesLit b ->+            VBytesLit b+        Natural ->+            VNatural+        NaturalLit n ->+            VNaturalLit n+        NaturalFold ->+            VPrim $ \n ->+            VPrim $ \natural ->+            VPrim $ \succ ->+            VPrim $ \zero ->+            let inert = VNaturalFold n natural succ zero+            in  case zero of+                VPrimVar -> inert+                _ -> case succ of+                    VPrimVar -> inert+                    _ -> case natural of+                        VPrimVar -> inert+                        _ -> case n of+                            VNaturalLit n' ->+                                -- Use an `Integer` for the loop, due to the+                                -- following issue:+                                --+                                -- https://github.com/ghcjs/ghcjs/issues/782+                                go zero (fromIntegral n' :: Integer) where+                                  go !acc 0 = acc+                                  go acc m =+                                  -- Detect a shortcut: if succ acc == acc then return acc immediately.+                                    let next = vApp succ acc+                                    in  if conv env next acc then acc else go next (m - 1)+                            _ -> inert+        NaturalBuild ->+            VPrim $ \case+                VPrimVar ->+                    VNaturalBuild VPrimVar+                t ->       t+                    `vApp` VNatural+                    `vApp` VHLam (Typed "n" VNatural) (\n -> vNaturalPlus n (VNaturalLit 1))+                    `vApp` VNaturalLit 0++        NaturalIsZero -> VPrim $ \case+            VNaturalLit n -> VBoolLit (n == 0)+            n             -> VNaturalIsZero n+        NaturalEven -> VPrim $ \case+            VNaturalLit n -> VBoolLit (even n)+            n             -> VNaturalEven n+        NaturalOdd -> VPrim $ \case+            VNaturalLit n -> VBoolLit (odd n)+            n             -> VNaturalOdd n+        NaturalToInteger -> VPrim $ \case+            VNaturalLit n -> VIntegerLit (fromIntegral n)+            n             -> VNaturalToInteger n+        NaturalShow -> VPrim $ \case+            VNaturalLit n -> VTextLit (VChunks [] (Text.pack (show n)))+            n             -> VNaturalShow n+        NaturalSubtract -> VPrim $ \case+            VNaturalLit 0 ->+                VHLam NaturalSubtractZero id+            x@(VNaturalLit m) ->+                VPrim $ \case+                    VNaturalLit n+                        | n >= m ->+                            -- Use an `Integer` for the subtraction, due to the+                            -- following issue:+                            --+                            -- https://github.com/ghcjs/ghcjs/issues/782+                            VNaturalLit (fromIntegral (subtract (fromIntegral m :: Integer) (fromIntegral n :: Integer)))+                        | otherwise -> VNaturalLit 0+                    y -> VNaturalSubtract x y+            x ->+                VPrim $ \case+                    VNaturalLit 0    -> VNaturalLit 0+                    y | conv env x y -> VNaturalLit 0+                    y                -> VNaturalSubtract x y+        NaturalPlus t u ->+            vNaturalPlus (eval env t) (eval env u)+        NaturalTimes t u ->+            case (eval env t, eval env u) of+                (VNaturalLit 1, u'           ) -> u'+                (t'           , VNaturalLit 1) -> t'+                (VNaturalLit 0, _            ) -> VNaturalLit 0+                (_            , VNaturalLit 0) -> VNaturalLit 0+                (VNaturalLit m, VNaturalLit n) -> VNaturalLit (m * n)+                (t'           , u'           ) -> VNaturalTimes t' u'+        Integer ->+            VInteger+        IntegerLit n ->+            VIntegerLit n+        IntegerClamp ->+            VPrim $ \case+                VIntegerLit n+                    | 0 <= n    -> VNaturalLit (fromInteger n)+                    | otherwise -> VNaturalLit 0+                n -> VIntegerClamp n+        IntegerNegate ->+            VPrim $ \case+                VIntegerLit n -> VIntegerLit (negate n)+                n             -> VIntegerNegate n+        IntegerShow ->+            VPrim $ \case+                VIntegerLit n+                    | 0 <= n    -> VTextLit (VChunks [] (Text.pack ('+':show n)))+                    | otherwise -> VTextLit (VChunks [] (Text.pack (show n)))+                n -> VIntegerShow n+        IntegerToDouble ->+            VPrim $ \case+                VIntegerLit n -> VDoubleLit (DhallDouble (read (show n)))+                -- `(read . show)` is used instead of `fromInteger`+                -- because `read` uses the correct rounding rule.+                -- See https://gitlab.haskell.org/ghc/ghc/issues/17231.+                n             -> VIntegerToDouble n+        Double ->+            VDouble+        DoubleLit n ->+            VDoubleLit n+        DoubleShow ->+            VPrim $ \case+                VDoubleLit (DhallDouble n) -> VTextLit (VChunks [] (Text.pack (show n)))+                n                          -> VDoubleShow n+        Text ->+            VText+        TextLit cs ->+            case evalChunks cs of+                VChunks [("", t)] "" -> t+                vcs                  -> VTextLit vcs+        TextAppend t u ->+            eval env (TextLit (Chunks [("", t), ("", u)] ""))+        TextShow ->+            VPrim $ \case+                VTextLit (VChunks [] x) -> VTextLit (VChunks [] (textShow x))+                t                       -> VTextShow t+        TextReplace ->+            VPrim $ \needle ->+            let hLamInfo0 = case needle of+                    VTextLit (VChunks [] "") -> TextReplaceEmpty+                    _                        -> Prim++            in  VHLam hLamInfo0 $ \replacement ->+            let hLamInfo1 = case needle of+                    VTextLit (VChunks [] "") ->+                        TextReplaceEmptyArgument replacement+                    _ ->+                        Prim+            in  VHLam hLamInfo1 $ \haystack ->+                    case needle of+                        VTextLit (VChunks [] "") ->+                            haystack++                        VTextLit (VChunks [] needleText) ->+                            case haystack of+                                VTextLit (VChunks [] haystackText) ->+                                    case replacement of+                                        VTextLit (VChunks [] replacementText) ->+                                            VTextLit $ VChunks []+                                                (Text.replace+                                                    needleText+                                                    replacementText+                                                    haystackText+                                                )+                                        _ ->+                                            VTextLit+                                                (vTextReplace+                                                    needleText+                                                    replacement+                                                    haystackText+                                                )+                                _ ->+                                    VTextReplace needle replacement haystack+                        _ ->+                            VTextReplace needle replacement haystack+        Date ->+            VDate+        DateLiteral d ->+            VDateLiteral d+        DateShow ->+            VPrim $ \case+                VDateLiteral d -> VTextLit (VChunks [] (dateShow d))+                t              -> VDateShow t+        Time ->+            VTime+        TimeLiteral t p ->+            VTimeLiteral t p+        TimeShow ->+            VPrim $ \case+                VTimeLiteral d p -> VTextLit (VChunks [] (timeShow d p))+                t                -> VTimeShow t+        TimeZone ->+            VTimeZone+        TimeZoneLiteral z ->+            VTimeZoneLiteral z+        TimeZoneShow ->+            VPrim $ \case+                VTimeZoneLiteral d -> VTextLit (VChunks [] (timezoneShow d))+                t                  -> VTimeZoneShow t+        List ->+            VPrim VList+        ListLit ma ts ->+            VListLit (fmap (eval env) ma) (fmap (eval env) ts)+        ListAppend t u ->+            vListAppend (eval env t) (eval env u)+        ListBuild ->+            VPrim $ \a ->+            VPrim $ \case+                VPrimVar ->+                    VListBuild a VPrimVar+                t ->       t+                    `vApp` VList a+                    `vApp` VHLam (Typed "a" a) (\x ->+                           VHLam (Typed "as" (VList a)) (\as ->+                           vListAppend (VListLit Nothing (pure x)) as))+                    `vApp` VListLit (Just (VList a)) mempty++        ListFold ->+            VPrim $ \a ->+            VPrim $ \as ->+            VPrim $ \list ->+            VPrim $ \cons ->+            VPrim $ \nil ->+            let inert = VListFold a as list cons nil+            in  case nil of+                VPrimVar -> inert+                _ -> case cons of+                    VPrimVar -> inert+                    _ -> case list of+                        VPrimVar -> inert+                        _ -> case a of+                            VPrimVar -> inert+                            _ -> case as of+                                VListLit _ as' ->+                                    foldr' (\x b -> cons `vApp` x `vApp` b) nil as'+                                _ -> inert+        ListLength ->+            VPrim $ \ a ->+            VPrim $ \case+                VListLit _ as -> VNaturalLit (fromIntegral (Sequence.length as))+                as            -> VListLength a as+        ListHead ->+            VPrim $ \ a ->+            VPrim $ \case+                VListLit _ as ->+                    case Sequence.viewl as of+                        y :< _ -> VSome y+                        _      -> VNone a+                as ->+                    VListHead a as+        ListLast ->+            VPrim $ \ a ->+            VPrim $ \case+                VListLit _ as ->+                    case Sequence.viewr as of+                        _ :> t -> VSome t+                        _      -> VNone a+                as -> VListLast a as+        ListIndexed ->+            VPrim $ \ a ->+            VPrim $ \case+                VListLit _ as ->+                    let a' =+                            if null as+                            then Just (VList (VRecord (Map.unorderedFromList [("index", VNatural), ("value", a)])))+                            else Nothing++                        as' =+                            Sequence.mapWithIndex+                                (\i t ->+                                    VRecordLit+                                        (Map.unorderedFromList+                                            [ ("index", VNaturalLit (fromIntegral i))+                                            , ("value", t)+                                            ]+                                        )+                                )+                                as++                        in  VListLit a' as'+                t ->+                    VListIndexed a t+        ListReverse ->+            VPrim $ \ ~a ->+            VPrim $ \case+                VListLit t as | null as ->+                    VListLit t as+                VListLit _ as ->+                    VListLit Nothing (Sequence.reverse as)+                t ->+                    VListReverse a t+        Optional ->+            VPrim VOptional+        Some t ->+            VSome (eval env t)+        None ->+            VPrim $ \ ~a -> VNone a+        Record kts ->+            VRecord (Map.sort (eval env . recordFieldValue <$> kts))+        RecordLit kts ->+            VRecordLit (Map.sort (eval env . recordFieldValue <$> kts))+        Union kts ->+            VUnion (Map.sort (fmap (fmap (eval env)) kts))+        Combine _ mk t u ->+            vCombine mk (eval env t) (eval env u)+        CombineTypes _ t u ->+            vCombineTypes (eval env t) (eval env u)+        Prefer _ _ t u ->+            vPrefer env (eval env t) (eval env u)+        RecordCompletion t u ->+            eval env (Annot (Prefer mempty PreferFromCompletion (Field t def) u) (Field t typ))+          where+            def = Syntax.makeFieldSelection "default"+            typ = Syntax.makeFieldSelection "Type"+        Merge x y ma ->+            case (eval env x, eval env y, fmap (eval env) ma) of+                (VRecordLit m, VInject _ k mt, _)+                    | Just f <- Map.lookup k m -> maybe f (vApp f) mt+                    | otherwise                -> error errorMsg+                (VRecordLit m, VSome t, _)+                    | Just f <- Map.lookup "Some" m -> vApp f t+                    | otherwise                     -> error errorMsg+                (VRecordLit m, VNone _, _)+                    | Just t <- Map.lookup "None" m -> t+                    | otherwise                     -> error errorMsg+                (x', y', ma') -> VMerge x' y' ma'+        ToMap x ma ->+            case (eval env x, fmap (eval env) ma) of+                (VRecordLit m, ma'@(Just _)) | null m ->+                    VListLit ma' Sequence.empty+                (VRecordLit m, _) ->+                    let entry (k, v) =+                            VRecordLit+                                (Map.unorderedFromList+                                    [ ("mapKey", VTextLit $ VChunks [] k)+                                    , ("mapValue", v)+                                    ]+                                )++                        s = (Sequence.fromList . map entry . Map.toAscList) m++                    in  VListLit Nothing s+                (x', ma') ->+                    VToMap x' ma'+        ShowConstructor x ->+            case eval env x of+                VInject m k _+                    | Just _ <- Map.lookup k m -> VTextLit (VChunks [] k)+                    | otherwise                -> error errorMsg+                VSome _ -> VTextLit (VChunks [] "Some")+                VNone _ -> VTextLit (VChunks [] "None")+                x' -> VShowConstructor x'+        Field t (Syntax.fieldSelectionLabel -> k) ->+            vField (eval env t) k+        Project t (Left ks) ->+            vProjectByFields env (eval env t) (Dhall.Set.sort (Dhall.Set.fromList ks))+        Project t (Right e) ->+            case eval env e of+                VRecord kts ->+                    vProjectByFields env (eval env t) (Dhall.Set.fromSet (Map.keysSet kts))+                e' ->+                    VProject (eval env t) (Right e')+        Assert t ->+            VAssert (eval env t)+        Equivalent _ t u ->+            VEquivalent (eval env t) (eval env u)+        With e₀ ks v ->+            vWith (eval env e₀) ks (eval env v)+        Note _ e ->+            eval env e+        ImportAlt t _ ->+            eval env t+        Embed a ->+            VEmbed a+  where+    evalChunks :: Chunks Void a -> VChunks a+    evalChunks (Chunks xys z) = foldr' cons nil xys+      where+        cons (x, t) vcs =+            case eval env t of+                VTextLit vcs' -> VChunks [] x <> vcs' <> vcs+                t'            -> VChunks [(x, t')] mempty <> vcs++        nil = VChunks [] z+    {-# INLINE evalChunks #-}++eqListBy :: (a -> a -> Bool) -> [a] -> [a] -> Bool+eqListBy f = go+  where+    go (x:xs) (y:ys) | f x y = go xs ys+    go [] [] = True+    go _  _  = False+{-# INLINE eqListBy #-}++eqMapsBy :: Ord k => (v -> v -> Bool) -> Map k v -> Map k v -> Bool+eqMapsBy f mL mR =+    Map.size mL == Map.size mR+    && eqListBy eq (Map.toAscList mL) (Map.toAscList mR)+  where+    eq (kL, vL) (kR, vR) = kL == kR && f vL vR+{-# INLINE eqMapsBy #-}++eqMaybeBy :: (a -> a -> Bool) -> Maybe a -> Maybe a -> Bool+eqMaybeBy f = go+  where+    go (Just x) (Just y) = f x y+    go Nothing  Nothing  = True+    go _        _        = False+{-# INLINE eqMaybeBy #-}++-- | Utility that powers the @Text/show@ built-in+textShow :: Text -> Text+textShow text = "\"" <> Text.concatMap f text <> "\""+  where+    f '"'  = "\\\""+    f '$'  = "\\u0024"+    f '\\' = "\\\\"+    f '\b' = "\\b"+    f '\n' = "\\n"+    f '\r' = "\\r"+    f '\t' = "\\t"+    f '\f' = "\\f"+    f c | c <= '\x1F' = Text.pack (Printf.printf "\\u%04x" (Data.Char.ord c))+        | otherwise   = Text.singleton c++-- | Utility that powers the @Date/show@ built-in+dateShow :: Day -> Text+dateShow = Text.pack . Time.formatTime Time.defaultTimeLocale "%0Y-%m-%d"++-- | Utility that powers the @Time/show@ built-in+timeShow :: TimeOfDay -> Word -> Text+timeShow (TimeOfDay hh mm seconds) precision =+    Text.pack (Printf.printf "%02d:%02d:%02d" hh mm ss <> suffix)+  where+    magnitude :: Integer+    magnitude = 10 ^ precision++    (ss, fraction) =+        truncate (seconds * fromInteger magnitude) `divMod` magnitude++    suffix+        | precision == 0 = ""+        | otherwise      = Printf.printf ".%0*d" precision fraction++-- | Utility that powers the @TimeZone/show@ built-in+timezoneShow :: TimeZone -> Text+timezoneShow = Text.pack . Time.formatTime Time.defaultTimeLocale "%Ez"++conv :: forall a. Eq a => Environment a -> Val a -> Val a -> Bool+conv !env t0 t0' =+    case (t0, t0') of+        (VConst k, VConst k') ->+            k == k'+        (VVar x i, VVar x' i') ->+            x == x' && i == i'+        (VLam _ (freshClosure -> (x, v, t)), VLam _ t' ) ->+            convSkip x (instantiate t v) (instantiate t' v)+        (VLam _ (freshClosure -> (x, v, t)), VHLam _ t') ->+            convSkip x (instantiate t v) (t' v)+        (VLam _ (freshClosure -> (x, v, t)), t'        ) ->+            convSkip x (instantiate t v) (vApp t' v)+        (VHLam _ t, VLam _ (freshClosure -> (x, v, t'))) ->+            convSkip x (t v) (instantiate t' v)+        (VHLam _ t, VHLam _ t'                    ) ->+            let (x, v) = fresh "x" in convSkip x (t v) (t' v)+        (VHLam _ t, t'                            ) ->+            let (x, v) = fresh "x" in convSkip x (t v) (vApp t' v)+        (t, VLam _ (freshClosure -> (x, v, t'))) ->+            convSkip x (vApp t v) (instantiate t' v)+        (t, VHLam _ t'  ) ->+            let (x, v) = fresh "x" in convSkip x (vApp t v) (t' v)+        (VApp t u, VApp t' u') ->+            conv env t t' && conv env u u'+        (VPi a b, VPi a' (freshClosure -> (x, v, b'))) ->+            conv env a a' && convSkip x (instantiate b v) (instantiate b' v)+        (VPi a b, VHPi (fresh -> (x, v)) a' b') ->+            conv env a a' && convSkip x (instantiate b v) (b' v)+        (VHPi _ a b, VPi a' (freshClosure -> (x, v, b'))) ->+            conv env a a' && convSkip x (b v) (instantiate b' v)+        (VHPi _ a b, VHPi (fresh -> (x, v)) a' b') ->+            conv env a a' && convSkip x (b v) (b' v)+        (VBool, VBool) ->+            True+        (VBoolLit b, VBoolLit b') ->+            b == b'+        (VBoolAnd t u, VBoolAnd t' u') ->+            conv env t t' && conv env u u'+        (VBoolOr t u, VBoolOr t' u') ->+            conv env t t' && conv env u u'+        (VBoolEQ t u, VBoolEQ t' u') ->+            conv env t t' && conv env u u'+        (VBoolNE t u, VBoolNE t' u') ->+            conv env t t' && conv env u u'+        (VBoolIf t u v, VBoolIf t' u' v') ->+            conv env t t' && conv env u u' && conv env v v'+        (VBytes, VBytes) ->+            True+        (VBytesLit l, VBytesLit r) ->+            l == r+        (VNatural, VNatural) ->+            True+        (VNaturalLit n, VNaturalLit n') ->+            n == n'+        (VNaturalFold t _ u v, VNaturalFold t' _ u' v') ->+            conv env t t' && conv env u u' && conv env v v'+        (VNaturalBuild t, VNaturalBuild t') ->+            conv env t t'+        (VNaturalIsZero t, VNaturalIsZero t') ->+            conv env t t'+        (VNaturalEven t, VNaturalEven t') ->+            conv env t t'+        (VNaturalOdd t, VNaturalOdd t') ->+            conv env t t'+        (VNaturalToInteger t, VNaturalToInteger t') ->+            conv env t t'+        (VNaturalShow t, VNaturalShow t') ->+            conv env t t'+        (VNaturalSubtract x y, VNaturalSubtract x' y') ->+            conv env x x' && conv env y y'+        (VNaturalPlus t u, VNaturalPlus t' u') ->+            conv env t t' && conv env u u'+        (VNaturalTimes t u, VNaturalTimes t' u') ->+            conv env t t' && conv env u u'+        (VInteger, VInteger) ->+            True+        (VIntegerLit t, VIntegerLit t') ->+            t == t'+        (VIntegerClamp t, VIntegerClamp t') ->+            conv env t t'+        (VIntegerNegate t, VIntegerNegate t') ->+            conv env t t'+        (VIntegerShow t, VIntegerShow t') ->+            conv env t t'+        (VIntegerToDouble t, VIntegerToDouble t') ->+            conv env t t'+        (VDouble, VDouble) ->+            True+        (VDoubleLit n, VDoubleLit n') ->+            n == n'+        (VDoubleShow t, VDoubleShow t') ->+            conv env t t'+        (VText, VText) ->+            True+        (VTextLit cs, VTextLit cs') ->+            convChunks cs cs'+        (VTextAppend t u, VTextAppend t' u') ->+            conv env t t' && conv env u u'+        (VTextShow t, VTextShow t') ->+            conv env t t'+        (VTextReplace a b c, VTextReplace a' b' c') ->+            conv env a a' && conv env b b' && conv env c c'+        (VDate, VDate) ->+            True+        (VDateLiteral l, VDateLiteral r) ->+            l == r+        (VDateShow t, VDateShow t') ->+            conv env t t'+        (VTime, VTime) ->+            True+        (VTimeLiteral tl pl, VTimeLiteral tr pr) ->+            tl == tr && pl == pr+        (VTimeShow t, VTimeShow t') ->+            conv env t t'+        (VTimeZone, VTimeZone) ->+            True+        (VTimeZoneLiteral l, VTimeZoneLiteral r) ->+            l == r+        (VTimeZoneShow t, VTimeZoneShow t') ->+            conv env t t'+        (VList a, VList a') ->+            conv env a a'+        (VListLit _ xs, VListLit _ xs') ->+            eqListBy (conv env) (toList xs) (toList xs')+        (VListAppend t u, VListAppend t' u') ->+            conv env t t' && conv env u u'+        (VListBuild _ t, VListBuild _ t') ->+            conv env t t'+        (VListLength a t, VListLength a' t') ->+            conv env a a' && conv env t t'+        (VListHead _ t, VListHead _ t') ->+            conv env t t'+        (VListLast _ t, VListLast _ t') ->+            conv env t t'+        (VListIndexed _ t, VListIndexed _ t') ->+            conv env t t'+        (VListReverse _ t, VListReverse _ t') ->+            conv env t t'+        (VListFold a l _ t u, VListFold a' l' _ t' u') ->+            conv env a a' && conv env l l' && conv env t t' && conv env u u'+        (VOptional a, VOptional a') ->+            conv env a a'+        (VSome t, VSome t') ->+            conv env t t'+        (VNone _, VNone _) ->+            True+        (VRecord m, VRecord m') ->+            eqMapsBy (conv env) m m'+        (VRecordLit m, VRecordLit m') ->+            eqMapsBy (conv env) m m'+        (VUnion m, VUnion m') ->+            eqMapsBy (eqMaybeBy (conv env)) m m'+        (VCombine _ t u, VCombine _ t' u') ->+            conv env t t' && conv env u u'+        (VCombineTypes t u, VCombineTypes t' u') ->+            conv env t t' && conv env u u'+        (VPrefer t u, VPrefer t' u') ->+            conv env t t' && conv env u u'+        (VMerge t u _, VMerge t' u' _) ->+            conv env t t' && conv env u u'+        (VToMap t _, VToMap t' _) ->+            conv env t t'+        (VShowConstructor t, VShowConstructor t') ->+            conv env t t'+        (VField t k, VField t' k') ->+            conv env t t' && k == k'+        (VProject t (Left ks), VProject t' (Left ks')) ->+            conv env t t' && ks == ks'+        (VProject t (Right e), VProject t' (Right e')) ->+            conv env t t' && conv env e e'+        (VAssert t, VAssert t') ->+            conv env t t'+        (VEquivalent t u, VEquivalent t' u') ->+            conv env t t' && conv env u u'+        (VInject m k mt, VInject m' k' mt') ->+            eqMapsBy (eqMaybeBy (conv env)) m m' && k == k' && eqMaybeBy (conv env) mt mt'+        (VEmbed a, VEmbed a') ->+            a == a'+        (_, _) ->+            False+  where+    fresh :: Text -> (Text, Val a)+    fresh x = (x, VVar x (countEnvironment x env))+    {-# INLINE fresh #-}++    freshClosure :: Closure a -> (Text, Val a, Closure a)+    freshClosure closure@(Closure x _ _) = (x, snd (fresh x), closure)+    {-# INLINE freshClosure #-}++    convChunks :: VChunks a -> VChunks a -> Bool+    convChunks (VChunks xys z) (VChunks xys' z') =+      eqListBy (\(x, y) (x', y') -> x == x' && conv env y y') xys xys' && z == z'+    {-# INLINE convChunks #-}++    convSkip :: Text -> Val a -> Val a -> Bool+    convSkip x = conv (Skip env x)+    {-# INLINE convSkip #-}++judgmentallyEqual :: Eq a => Expr s a -> Expr t a -> Bool+judgmentallyEqual (Syntax.denote -> t) (Syntax.denote -> u) =+    conv Empty (eval Empty t) (eval Empty u)+{-# INLINABLE judgmentallyEqual #-}++data Names+  = EmptyNames+  | Bind !Names {-# UNPACK #-} !Text+  deriving Show++envNames :: Environment a -> Names+envNames Empty = EmptyNames+envNames (Skip   env x  ) = Bind (envNames env) x+envNames (Extend env x _) = Bind (envNames env) x++countNames :: Text -> Names -> Int+countNames x = go 0+  where+    go !acc EmptyNames         = acc+    go  acc (Bind env x') = go (if x == x' then acc + 1 else acc) env++-- | Quote a value into beta-normal form.+quote :: forall a. Eq a => Names -> Val a -> Expr Void a+quote !env !t0 =+    case t0 of+        VConst k ->+            Const k+        VVar !x !i ->+            Var (V x (countNames x env - i - 1))+        VApp t u ->+            quote env t `qApp` u+        VLam a (freshClosure -> (x, v, t)) ->+            Lam+                mempty+                (Syntax.makeFunctionBinding x (quote env a))+                (quoteBind x (instantiate t v))+        VHLam i t ->+            case i of+                Typed (fresh -> (x, v)) a ->+                    Lam mempty+                        (Syntax.makeFunctionBinding x (quote env a))+                        (quoteBind x (t v))+                Prim ->+                    quote env (t VPrimVar)+                NaturalSubtractZero ->+                    App NaturalSubtract (NaturalLit 0)+                TextReplaceEmpty ->+                    App TextReplace (TextLit (Chunks [] ""))+                TextReplaceEmptyArgument replacement ->+                    App (App TextReplace (TextLit (Chunks [] "")))+                        (quote env replacement)++        VPi a (freshClosure -> (x, v, b)) ->+            Pi mempty x (quote env a) (quoteBind x (instantiate b v))+        VHPi (fresh -> (x, v)) a b ->+            Pi mempty x (quote env a) (quoteBind x (b v))+        VBool ->+            Bool+        VBoolLit b ->+            BoolLit b+        VBoolAnd t u ->+            BoolAnd (quote env t) (quote env u)+        VBoolOr t u ->+            BoolOr (quote env t) (quote env u)+        VBoolEQ t u ->+            BoolEQ (quote env t) (quote env u)+        VBoolNE t u ->+            BoolNE (quote env t) (quote env u)+        VBoolIf t u v ->+            BoolIf (quote env t) (quote env u) (quote env v)+        VBytes ->+            Bytes+        VBytesLit b ->+            BytesLit b+        VNatural ->+            Natural+        VNaturalLit n ->+            NaturalLit n+        VNaturalFold a t u v ->+            NaturalFold `qApp` a `qApp` t `qApp` u `qApp` v+        VNaturalBuild t ->+            NaturalBuild `qApp` t+        VNaturalIsZero t ->+            NaturalIsZero `qApp` t+        VNaturalEven t ->+            NaturalEven `qApp` t+        VNaturalOdd t ->+            NaturalOdd `qApp` t+        VNaturalToInteger t ->+            NaturalToInteger `qApp` t+        VNaturalShow t ->+            NaturalShow `qApp` t+        VNaturalPlus t u ->+            NaturalPlus (quote env t) (quote env u)+        VNaturalTimes t u ->+            NaturalTimes (quote env t) (quote env u)+        VNaturalSubtract x y ->+            NaturalSubtract `qApp` x `qApp` y+        VInteger ->+            Integer+        VIntegerLit n ->+            IntegerLit n+        VIntegerClamp t ->+            IntegerClamp `qApp` t+        VIntegerNegate t ->+            IntegerNegate `qApp` t+        VIntegerShow t ->+            IntegerShow `qApp` t+        VIntegerToDouble t ->+            IntegerToDouble `qApp` t+        VDouble ->+            Double+        VDoubleLit n ->+            DoubleLit n+        VDoubleShow t ->+            DoubleShow `qApp` t+        VText ->+            Text+        VTextLit (VChunks xys z) ->+            TextLit (Chunks (fmap (fmap (quote env)) xys) z)+        VTextAppend t u ->+            TextAppend (quote env t) (quote env u)+        VTextShow t ->+            TextShow `qApp` t+        VTextReplace a b c ->+            TextReplace `qApp` a `qApp` b `qApp` c+        VDate ->+            Date+        VDateLiteral d ->+            DateLiteral d+        VDateShow t ->+            DateShow `qApp` t+        VTime ->+            Time+        VTimeLiteral t p ->+            TimeLiteral t p+        VTimeShow t ->+            TimeShow `qApp` t+        VTimeZone ->+            TimeZone+        VTimeZoneLiteral z ->+            TimeZoneLiteral z+        VTimeZoneShow t ->+            TimeZoneShow `qApp` t+        VList t ->+            List `qApp` t+        VListLit ma ts ->+            ListLit (fmap (quote env) ma) (fmap (quote env) ts)+        VListAppend t u ->+            ListAppend (quote env t) (quote env u)+        VListBuild a t ->+            ListBuild `qApp` a `qApp` t+        VListFold a l t u v ->+            ListFold `qApp` a `qApp` l `qApp` t `qApp` u `qApp` v+        VListLength a t ->+            ListLength `qApp` a `qApp` t+        VListHead a t ->+            ListHead `qApp` a `qApp` t+        VListLast a t ->+            ListLast `qApp` a `qApp` t+        VListIndexed a t ->+            ListIndexed `qApp` a `qApp` t+        VListReverse a t ->+            ListReverse `qApp` a `qApp` t+        VOptional a ->+            Optional `qApp` a+        VSome t ->+            Some (quote env t)+        VNone t ->+            None `qApp` t+        VRecord m ->+            Record (fmap quoteRecordField m)+        VRecordLit m ->+            RecordLit (fmap quoteRecordField m)+        VUnion m ->+            Union (fmap (fmap (quote env)) m)+        VCombine mk t u ->+            Combine mempty mk (quote env t) (quote env u)+        VCombineTypes t u ->+            CombineTypes mempty (quote env t) (quote env u)+        VPrefer t u ->+            Prefer mempty PreferFromSource (quote env t) (quote env u)+        VMerge t u ma ->+            Merge (quote env t) (quote env u) (fmap (quote env) ma)+        VToMap t ma ->+            ToMap (quote env t) (fmap (quote env) ma)+        VShowConstructor t ->+            ShowConstructor (quote env t)+        VField t k ->+            Field (quote env t) $ Syntax.makeFieldSelection k+        VProject t p ->+            Project (quote env t) (first Dhall.Set.toList (fmap (quote env) p))+        VAssert t ->+            Assert (quote env t)+        VEquivalent t u ->+            Equivalent mempty (quote env t) (quote env u)+        VWith e ks v ->+            With (quote env e) ks (quote env v)+        VInject m k Nothing ->+            Field (Union (fmap (fmap (quote env)) m)) $ Syntax.makeFieldSelection k+        VInject m k (Just t) ->+            Field (Union (fmap (fmap (quote env)) m)) (Syntax.makeFieldSelection k) `qApp` t+        VEmbed a ->+            Embed a+        VPrimVar ->+            error errorMsg+  where+    fresh :: Text -> (Text, Val a)+    fresh x = (x, VVar x (countNames x env))+    {-# INLINE fresh #-}++    freshClosure :: Closure a -> (Text, Val a, Closure a)+    freshClosure closure@(Closure x _ _) = (x, snd (fresh x), closure)+    {-# INLINE freshClosure #-}++    quoteBind :: Text -> Val a -> Expr Void a+    quoteBind x = quote (Bind env x)+    {-# INLINE quoteBind #-}++    qApp :: Expr Void a -> Val a -> Expr Void a+    qApp t VPrimVar = t+    qApp t u        = App t (quote env u)+    {-# INLINE qApp #-}++    quoteRecordField :: Val a -> RecordField Void a+    quoteRecordField = Syntax.makeRecordField . quote env+    {-# INLINE quoteRecordField #-}++-- | Normalize an expression in an environment of values. Any variable pointing out of+--   the environment is treated as opaque free variable.+nf :: Eq a => Environment a -> Expr s a -> Expr t a+nf !env = Syntax.renote . quote (envNames env) . eval env . Syntax.denote++normalize :: Eq a => Expr s a -> Expr t a+normalize = nf Empty+{-# INLINABLE normalize #-}++alphaNormalize :: Expr s a -> Expr s a+alphaNormalize = goEnv EmptyNames+  where+    goVar :: Names -> Text -> Int -> Expr s a+    goVar e topX topI = go 0 e topI+      where+        go !acc (Bind env x) !i+          | x == topX = if i == 0 then Var (V "_" acc) else go (acc + 1) env (i - 1)+          | otherwise = go (acc + 1) env i+        go _ EmptyNames i = Var (V topX i)++    goEnv :: Names -> Expr s a -> Expr s a+    goEnv !e0 t0 =+        case t0 of+            Const k ->+                Const k+            Var (V x i) ->+                goVar e0 x i+            Lam cs (FunctionBinding src0 x src1 src2 t) u ->+                Lam cs (FunctionBinding src0 "_" src1 src2 (go t)) (goBind x u)+            Pi cs x a b ->+                Pi cs "_" (go a) (goBind x b)+            App t u ->+                App (go t) (go u)+            Let (Binding src0 x src1 mA src2 a) b ->+                Let (Binding src0 "_" src1 (fmap (fmap go) mA) src2 (go a)) (goBind x b)+            Annot t u ->+                Annot (go t) (go u)+            Bool ->+                Bool+            BoolLit b ->+                BoolLit b+            BoolAnd t u ->+                BoolAnd (go t) (go u)+            BoolOr t u ->+                BoolOr  (go t) (go u)+            BoolEQ t u ->+                BoolEQ  (go t) (go u)+            BoolNE t u ->+                BoolNE  (go t) (go u)+            BoolIf b t f ->+                BoolIf  (go b) (go t) (go f)+            Bytes ->+                Bytes+            BytesLit b ->+                BytesLit b+            Natural ->+                Natural+            NaturalLit n ->+                NaturalLit n+            NaturalFold ->+                NaturalFold+            NaturalBuild ->+                NaturalBuild+            NaturalIsZero ->+                NaturalIsZero+            NaturalEven ->+                NaturalEven+            NaturalOdd ->+                NaturalOdd+            NaturalToInteger ->+                NaturalToInteger+            NaturalShow ->+                NaturalShow+            NaturalSubtract ->+                NaturalSubtract+            NaturalPlus t u ->+                NaturalPlus (go t) (go u)+            NaturalTimes t u ->+                NaturalTimes (go t) (go u)+            Integer ->+                Integer+            IntegerLit n ->+                IntegerLit n+            IntegerClamp ->+                IntegerClamp+            IntegerNegate ->+                IntegerNegate+            IntegerShow ->+                IntegerShow+            IntegerToDouble ->+                IntegerToDouble+            Double ->+                Double+            DoubleLit n ->+                DoubleLit n+            DoubleShow ->+                DoubleShow+            Text ->+                Text+            TextLit cs ->+                TextLit (goChunks cs)+            TextAppend t u ->+                TextAppend (go t) (go u)+            TextShow ->+                TextShow+            TextReplace ->+                TextReplace+            Date ->+                Date+            DateLiteral d ->+                DateLiteral d+            DateShow ->+                DateShow+            Time ->+                Time+            TimeLiteral t p ->+                TimeLiteral t p+            TimeShow ->+                TimeShow+            TimeZone ->+                TimeZone+            TimeZoneLiteral z ->+                TimeZoneLiteral z+            TimeZoneShow ->+                TimeZoneShow+            List ->+                List+            ListLit ma ts ->+                ListLit (fmap go ma) (fmap go ts)+            ListAppend t u ->+                ListAppend (go t) (go u)+            ListBuild ->+                ListBuild+            ListFold ->+                ListFold+            ListLength ->+                ListLength+            ListHead ->+                ListHead+            ListLast ->+                ListLast+            ListIndexed ->+                ListIndexed+            ListReverse ->+                ListReverse+            Optional ->+                Optional+            Some t ->+                Some (go t)+            None ->+                None+            Record kts ->+                Record (goRecordField <$> kts)+            RecordLit kts ->+                RecordLit (goRecordField <$> kts)+            Union kts ->+                Union (fmap (fmap go) kts)+            Combine cs m t u ->+                Combine cs m (go t) (go u)+            CombineTypes cs t u ->+                CombineTypes cs (go t) (go u)+            Prefer cs b t u ->+                Prefer cs b (go t) (go u)+            RecordCompletion t u ->+                RecordCompletion (go t) (go u)+            Merge x y ma ->+                Merge (go x) (go y) (fmap go ma)+            ToMap x ma ->+                ToMap (go x) (fmap go ma)+            ShowConstructor x ->+                ShowConstructor (go x)+            Field t k ->+                Field (go t) k+            Project t ks ->+                Project (go t) (fmap go ks)+            Assert t ->+                Assert (go t)+            Equivalent cs t u ->+                Equivalent cs (go t) (go u)+            With e k v ->+                With (go e) k (go v)+            Note s e ->+                Note s (go e)+            ImportAlt t u ->+                ImportAlt (go t) (go u)+            Embed a ->+                Embed a+      where+        go                     = goEnv e0+        goBind x               = goEnv (Bind e0 x)+        goChunks (Chunks ts x) = Chunks (fmap (fmap go) ts) x+        goRecordField (RecordField s0 e s1 s2) = RecordField s0 (go e) s1 s2
− src/Dhall/Eval.hs-boot
@@ -1,8 +0,0 @@--module Dhall.Eval where--import {-# SOURCE #-} Dhall.Core--convEmpty      :: Eq a => Expr s a -> Expr t a -> Bool-nfEmpty        :: Eq a => Expr s a -> Expr t a-alphaNormalize :: Expr s a -> Expr s a
src/Dhall/Format.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE DeriveAnyClass    #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards   #-} @@ -7,104 +6,117 @@ module Dhall.Format     ( -- * Format       Format(..)-    , FormatMode(..)     , format     ) where -import Control.Exception (Exception)-import Dhall.Parser (exprAndHeaderFromText)-import Dhall.Pretty (CharacterSet(..), annToAnsiStyle, layoutOpts)--import Data.Monoid ((<>))+import Data.Foldable      (for_)+import Data.List.NonEmpty (NonEmpty)+import Data.Maybe         (fromMaybe)+import Dhall.Pretty       (CharacterSet, annToAnsiStyle, detectCharacterSet)+import Dhall.Util+    ( Censor+    , CheckFailed (..)+    , Header (..)+    , Input (..)+    , OutputMode (..)+    , Transitivity (..)+    , handleMultipleChecksFailed+    ) -import qualified Data.Text.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.Core+import qualified Dhall.Import import qualified Dhall.Pretty+import qualified Dhall.Util+import qualified Prettyprinter                      as Pretty+import qualified Prettyprinter.Render.Terminal      as Pretty.Terminal+import qualified Prettyprinter.Render.Text          as Pretty.Text+import qualified System.AtomicWrite.Writer.LazyText as AtomicWrite.LazyText import qualified System.Console.ANSI+import qualified System.FilePath import qualified System.IO -data NotFormatted = NotFormatted-    deriving (Exception)--instance Show NotFormatted where-    show _ = ""- -- | Arguments to the `format` subcommand data Format = Format-    { characterSet :: CharacterSet-    , formatMode   :: FormatMode+    { chosenCharacterSet :: Maybe CharacterSet+    , censor             :: Censor+    , transitivity       :: Transitivity+    , inputs             :: NonEmpty Input+    , outputMode         :: OutputMode     } -{-| The `format` subcommand can either `Modify` its input or simply `Check`-    that the input is already formatted--}-data FormatMode-    = Modify-        { inplace :: Maybe FilePath-          -- ^ Modify file in-place if present, otherwise read from @stdin@ and-          --   write to @stdout@-        }-    | Check-        { path :: Maybe FilePath-          -- ^ Read from the given file if present, otherwise read from @stdin@-        }- -- | Implementation of the @dhall format@ subcommand-format-    :: Format-    -> IO ()-format (Format {..}) =-    case formatMode of-        Modify {..} ->-            case inplace of-                Just file -> do-                    text <- Data.Text.IO.readFile file+format :: Format -> IO ()+format (Format { inputs = inputs0, transitivity = transitivity0, ..}) =+    handleMultipleChecksFailed "format" "formatted" go inputs0+  where+    go input = do+        let directory = case input of+                StandardInput ->+                    "."+                InputFile file ->+                    System.FilePath.takeDirectory file -                    (header, expr) <- Dhall.Core.throws (exprAndHeaderFromText "(stdin)" text)+        let status = Dhall.Import.emptyStatus directory -                    let doc =   Pretty.pretty header-                            <>  Pretty.unAnnotate (Dhall.Pretty.prettyCharacterSet characterSet expr)-                            <>  "\n"-                    System.IO.withFile file System.IO.WriteMode (\handle -> do-                        Pretty.Terminal.renderIO handle (Pretty.layoutSmart layoutOpts doc))-                Nothing -> do-                    inText <- Data.Text.IO.getContents+        let layoutHeaderAndExpr (Header header, expr) =+                let characterSet = fromMaybe (detectCharacterSet expr) chosenCharacterSet+                in+                Dhall.Pretty.layout+                    (   Pretty.pretty header+                    <>  Dhall.Pretty.prettyCharacterSet characterSet expr+                    <>  "\n") -                    (header, expr) <- Dhall.Core.throws (exprAndHeaderFromText "(stdin)" inText)+        (inputName, originalText, transitivity) <- case input of+            InputFile file -> do+                text <- Data.Text.IO.readFile file -                    let doc =   Pretty.pretty header-                            <>  Dhall.Pretty.prettyCharacterSet characterSet expr-                            <>  "\n"+                return (file, text, transitivity0)+            StandardInput -> do+                text <- Data.Text.IO.getContents -                    supportsANSI <- System.Console.ANSI.hSupportsANSI System.IO.stdout+                return ("(input)", text, NonTransitive) -                    if supportsANSI-                      then-                        Pretty.Terminal.renderIO-                          System.IO.stdout-                          (fmap annToAnsiStyle (Pretty.layoutSmart layoutOpts doc))-                      else-                        Pretty.Terminal.renderIO-                          System.IO.stdout-                          (Pretty.layoutSmart layoutOpts (Pretty.unAnnotate doc))-        Check {..} -> do-            originalText <- case path of-                Just file -> Data.Text.IO.readFile file-                Nothing   -> Data.Text.IO.getContents -            (header, expr) <- Dhall.Core.throws (exprAndHeaderFromText "(stdin)" originalText)+        headerAndExpr@(_, parsedExpression) <- Dhall.Util.getExpressionAndHeaderFromStdinText censor inputName originalText -            let doc =   Pretty.pretty header-                    <>  Pretty.unAnnotate (Dhall.Pretty.prettyCharacterSet characterSet expr)-                    <>  "\n"+        case transitivity of+            Transitive ->+                for_ parsedExpression $ \import_ -> do+                    maybeFilepath <- Dhall.Import.dependencyToFile status import_ -            let formattedText =-                    Pretty.Text.renderStrict (Pretty.layoutSmart layoutOpts doc)+                    for_ maybeFilepath $ \filepath ->+                        go (InputFile filepath) -            if originalText == formattedText-                then return ()-                else Control.Exception.throwIO NotFormatted+            NonTransitive ->+                return ()++        let docStream = layoutHeaderAndExpr headerAndExpr++        let formattedText = Pretty.Text.renderStrict docStream++        case outputMode of+            Write -> do+                case input of+                    InputFile file ->+                        if originalText == formattedText+                            then return ()+                            else AtomicWrite.LazyText.atomicWriteFile+                                    file+                                    (Pretty.Text.renderLazy docStream)++                    StandardInput -> do+                        supportsANSI <- System.Console.ANSI.hSupportsANSI System.IO.stdout++                        Pretty.Terminal.renderIO+                            System.IO.stdout+                            (if supportsANSI+                                then (fmap annToAnsiStyle docStream)+                                else (Pretty.unAnnotateS docStream))++                return (Right ())++            Check ->+                return $+                    if originalText == formattedText+                        then Right ()+                        else Left CheckFailed{..}
src/Dhall/Freeze.hs view
@@ -1,52 +1,188 @@ {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes        #-} {-# LANGUAGE RecordWildCards   #-}+{-# LANGUAGE ViewPatterns      #-}  -- | This module contains the implementation of the @dhall freeze@ subcommand  module Dhall.Freeze     ( -- * Freeze       freeze+    , freezeExpression     , freezeImport     , freezeRemoteImport +      -- * Freeze with custom evaluation settings+    , freezeWithSettings+    , freezeExpressionWithSettings+    , freezeImportWithSettings+    , freezeRemoteImportWithSettings+       -- * Types     , Scope(..)     , Intent(..)++      -- * Deprecated functions+    , freezeWithManager+    , freezeExpressionWithManager+    , freezeImportWithManager+    , freezeRemoteImportWithManager     ) where -import Control.Exception (SomeException)-import Data.Monoid ((<>))-import Data.Maybe (fromMaybe)-import Data.Text-import Dhall.Binary (StandardVersion(..))-import Dhall.Core (Expr(..), Import(..), ImportHashed(..), ImportType(..))-import Dhall.Import (standardVersion)-import Dhall.Parser (exprAndHeaderFromText, Src)-import Dhall.Pretty (CharacterSet, annToAnsiStyle, layoutOpts, prettyCharacterSet)-import Dhall.TypeCheck (X)-import Lens.Family (set)+import Data.Foldable       (for_)+import Data.List.NonEmpty  (NonEmpty)+import Data.Maybe          (fromMaybe)+import Dhall               (EvaluateSettings)+import Dhall.Pretty        (CharacterSet, detectCharacterSet)+import Dhall.Syntax+    ( Expr (..)+    , Import (..)+    , ImportHashed (..)+    , ImportType (..)+    )+import Dhall.Util+    ( Censor+    , CheckFailed (..)+    , Header (..)+    , Input (..)+    , OutputMode (..)+    , Transitivity (..)+    , handleMultipleChecksFailed+    )+import Lens.Micro          (set, transformMOf, transformOf)+import Lens.Micro.Extras   (view) import System.Console.ANSI (hSupportsANSI) -import qualified Control.Exception-import qualified Control.Monad.Trans.State.Strict          as State-import qualified Data.Text.Prettyprint.Doc                 as Pretty-import qualified Data.Text.Prettyprint.Doc.Render.Terminal as Pretty-import qualified Data.Text.IO-import qualified Dhall.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.Pretty import qualified Dhall.TypeCheck+import qualified Dhall.Util                         as Util+import qualified Prettyprinter                      as Pretty+import qualified Prettyprinter.Render.Terminal      as Pretty+import qualified Prettyprinter.Render.Text          as Pretty.Text+import qualified System.AtomicWrite.Writer.LazyText as AtomicWrite.LazyText import qualified System.FilePath import qualified System.IO +-- | Specifies which imports to freeze+data Scope+    = OnlyRemoteImports+    -- ^ Freeze only remote imports (i.e. URLs)+    | AllImports+    -- ^ Freeze all imports (including paths and environment variables)++-- | Specifies why we are adding semantic integrity checks+data Intent+    = Secure+    -- ^ Protect imports with an integrity check without a fallback so that+    --   import resolution fails if the import changes+    | Cache+    -- ^ Protect imports with an integrity check and also add a fallback import+    --   import without an integrity check.  This is useful if you only want to+    --   cache imports when possible but still gracefully degrade to resolving+    --   them if the semantic integrity check has changed.+ -- | Retrieve an `Import` and update the hash to match the latest contents freezeImport     :: FilePath     -- ^ Current working directory-    -> StandardVersion     -> Import     -> IO Import-freezeImport directory _standardVersion 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 =@@ -55,133 +191,186 @@                         }                 } -    let status =-            set standardVersion-                _standardVersion-                (Dhall.Import.emptyStatus directory)--    let download =-            State.evalStateT (Dhall.Import.loadWith (Embed import_)) status--    -- Try again without the semantic integrity check if decoding fails-    let handler :: SomeException -> IO (Expr Src X)-        handler _ = do-            State.evalStateT (Dhall.Import.loadWith (Embed unprotectedImport)) status+    let status = Dhall.Import.emptyStatusWithManager (view Dhall.newManager settings) directory -    expression <- Control.Exception.handle handler download+    expression <- State.evalStateT (Dhall.Import.loadWith (Embed unprotectedImport)) status -    case Dhall.TypeCheck.typeOf expression of-        Left  exception -> Control.Exception.throwIO exception+    case Dhall.TypeCheck.typeWith (view Dhall.startingContext settings) expression of+        Left  exception -> Exception.throwIO exception         Right _         -> return () -    let normalizedExpression =-            Dhall.Core.alphaNormalize (Dhall.Core.normalize expression)+    let normalizedExpression = Core.alphaNormalize (Core.normalizeWith (view Dhall.normalizer settings) expression) -    let expressionHash =-            Just (Dhall.Import.hashExpression _standardVersion normalizedExpression)+    -- make sure the frozen import is present in the semantic cache+    Dhall.Import.writeExpressionToSemanticCache (Core.denote expression) -    let newImportHashed = (importHashed import_) { hash = expressionHash }+    let expressionHash = Dhall.Import.hashExpression normalizedExpression -    let newImport = import_ { importHashed = newImportHashed }+    let newImportHashed = (importHashed import_) { hash = Just expressionHash } -    State.evalStateT (Dhall.Import.exprToImport newImport normalizedExpression) status+    let newImport = import_ { importHashed = newImportHashed }      return newImport --- | Freeze an import only if the import is a `Remote` import-freezeRemoteImport-    :: FilePath-    -- ^ Current working directory-    -> StandardVersion+-- | See 'freezeRemoteImport'.+freezeRemoteImportWithSettings+    :: EvaluateSettings+    -> FilePath     -> Import     -> IO Import-freezeRemoteImport directory _standardVersion import_ = do+freezeRemoteImportWithSettings settings directory import_ =     case importType (importHashed import_) of-        Remote {} -> freezeImport directory _standardVersion import_+        Remote {} -> freezeImportWithSettings settings directory import_         _         -> return import_ -writeExpr :: Maybe FilePath -> (Text, Expr s Import) -> CharacterSet -> IO ()-writeExpr inplace (header, expr) characterSet = do-    let doc =  Pretty.pretty header-            <> Dhall.Pretty.prettyCharacterSet characterSet expr+-- | See 'freezeRemoteImport'.+freezeNonMissingImportWithSettings+    :: EvaluateSettings+    -> FilePath+    -> Import+    -> IO Import+freezeNonMissingImportWithSettings settings directory import_ =+    case importType (importHashed import_) of+        Missing -> return import_+        _ -> freezeImportWithSettings settings directory import_ -    let unAnnotated = Pretty.layoutSmart layoutOpts (Pretty.unAnnotate doc)+-- | See 'freeze'.+freezeWithSettings+    :: EvaluateSettings+    -> OutputMode+    -> Transitivity+    -> NonEmpty Input+    -> Scope+    -> Intent+    -> Maybe CharacterSet+    -> Censor+    -> IO ()+freezeWithSettings settings outputMode transitivity0 inputs scope intent chosenCharacterSet censor =+    handleMultipleChecksFailed "freeze" "frozen" go inputs+  where+    go input = do+        let directory = case input of+                StandardInput ->+                    "."+                InputFile file ->+                    System.FilePath.takeDirectory file -    case inplace of-        Just f ->-            System.IO.withFile f System.IO.WriteMode (\handle -> do-                Pretty.renderIO handle unAnnotated-                Data.Text.IO.hPutStrLn handle "" )+        let status = Dhall.Import.emptyStatusWithManager (view Dhall.newManager settings) directory -        Nothing -> do-            supportsANSI <- System.Console.ANSI.hSupportsANSI System.IO.stdout-            if supportsANSI-               then-                 Pretty.renderIO System.IO.stdout (annToAnsiStyle <$> Pretty.layoutSmart layoutOpts doc)-               else-                 Pretty.renderIO System.IO.stdout unAnnotated+        (inputName, originalText, transitivity) <- case input of+            InputFile file -> do+                text <- Text.IO.readFile file --- | Specifies which imports to freeze-data Scope-    = OnlyRemoteImports-    -- ^ Freeze only remote imports (i.e. URLs)-    | AllImports-    -- ^ Freeze all imports (including paths and environment variables)+                return (file, text, transitivity0) --- | 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.+            StandardInput -> do+                text <- Text.IO.getContents --- | Implementation of the @dhall freeze@ subcommand-freeze-    :: Maybe FilePath-    -- ^ Modify file in-place if present, otherwise read from @stdin@ and write-    --   to @stdout@-    -> Scope-    -> Intent-    -> CharacterSet-    -> StandardVersion-    -> IO ()-freeze inplace scope intent characterSet _standardVersion = do-    (text, directory) <- case inplace of-        Nothing -> do-            text <- Data.Text.IO.getContents+                return ("(input)", text, NonTransitive) -            return (text, ".")+        (Header header, parsedExpression) <- Util.getExpressionAndHeaderFromStdinText censor inputName originalText -        Just file -> do-            text <- Data.Text.IO.readFile file+        let characterSet = fromMaybe (detectCharacterSet parsedExpression) chosenCharacterSet -            return (text, System.FilePath.takeDirectory file)+        case transitivity of+            Transitive ->+                for_ parsedExpression $ \import_ -> do+                    maybeFilepath <- Dhall.Import.dependencyToFile status import_ -    (header, parsedExpression) <- Dhall.Core.throws (exprAndHeaderFromText srcInfo text)+                    for_ maybeFilepath $ \filepath ->+                        go (InputFile filepath) +            NonTransitive ->+                return ()++        frozenExpression <- freezeExpressionWithSettings settings directory scope intent parsedExpression++        let doc =  Pretty.pretty header+                <> Dhall.Pretty.prettyCharacterSet characterSet frozenExpression+                <> "\n"++        let stream = Dhall.Pretty.layout doc++        let modifiedText = Pretty.Text.renderStrict stream++        case outputMode of+            Write -> do+                let unAnnotated = Pretty.unAnnotateS stream++                case input of+                    InputFile file ->+                        if originalText == modifiedText+                            then return ()+                            else+                                AtomicWrite.LazyText.atomicWriteFile+                                    file+                                    (Pretty.Text.renderLazy unAnnotated)++                    StandardInput -> do+                        supportsANSI <- System.Console.ANSI.hSupportsANSI System.IO.stdout+                        if supportsANSI+                           then+                             Pretty.renderIO System.IO.stdout (Dhall.Pretty.annToAnsiStyle <$> stream)+                           else+                             Pretty.renderIO System.IO.stdout unAnnotated++                return (Right ())++            Check ->+                return $+                    if originalText == modifiedText+                        then Right ()+                        else Left CheckFailed{..}++-- | See 'freezeExpression'.+freezeExpressionWithSettings+    :: EvaluateSettings+    -> FilePath+    -> Scope+    -> Intent+    -> Expr s Import+    -> IO (Expr s Import)+freezeExpressionWithSettings settings directory scope intent expression = do     let freezeScope =             case scope of-                AllImports        -> freezeImport-                OnlyRemoteImports -> freezeRemoteImport+                AllImports        -> freezeNonMissingImportWithSettings+                OnlyRemoteImports -> freezeRemoteImportWithSettings -    let freezeFunction = freezeScope directory _standardVersion+    let freezeFunction = freezeScope settings directory      let cache+            -- This case is necessary because `transformOf` is a bottom-up+            -- rewrite rule.   Without this rule, if you were to transform a+            -- file that already has a cached expression, like this:+            --+            --     someImport sha256:… ? someImport+            --+            -- ... then you would get:+            --+            --       (someImport sha256:… ? someImport)+            --     ? (someImport sha256:… ? someImport)+            --+            -- ... and this rule fixes that by collapsing that back to:+            --+            --       (someImport sha256:… ? someImport)             (ImportAlt-                (Embed-                    (Import { importHashed = ImportHashed { hash = Just _expectedHash } })+                (Core.shallowDenote -> ImportAlt+                    (Core.shallowDenote -> Embed+                        Import{ importHashed = ImportHashed{ hash = Just _expectedHash } }+                    )+                    (Core.shallowDenote -> Embed+                        Import{ importHashed = ImportHashed{ hash = Nothing } }+                    )                 )-                import_@(ImportAlt-                    (Embed-                        (Import { importHashed = ImportHashed { hash = Just _actualHash } })+                import_@(Core.shallowDenote -> ImportAlt+                    (Core.shallowDenote -> Embed+                        Import{ importHashed = ImportHashed{ hash = Just _actualHash } }                     )-                    _+                    (Core.shallowDenote -> Embed+                        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@@ -195,27 +384,62 @@             (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+                   `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 expression = do-            return expression+        cache+            (Embed import_@(Import { importHashed = ImportHashed { hash = Just _ } })) = do+                -- Regenerate the integrity check, just in case it's wrong+                frozenImport <- freezeFunction import_ -    let rewrite expression =-            case intent of-                Secure ->-                    traverse freezeFunction expression-                Cache  ->-                    Dhall.Optics.transformMOf-                        Dhall.Core.subExpressions-                        cache-                        (Dhall.Core.denote expression)+                let frozenMissing = toMissing frozenImport -    frozenExpression <- rewrite parsedExpression+                -- `dhall freeze --cache` also works the other way around, adding an+                -- unprotected fallback import to imports that are already+                -- protected+                let thawedImport = import_+                        { importHashed = (importHashed import_)+                            { hash = Nothing+                            }+                        } -    writeExpr inplace (header, frozenExpression) characterSet-        where-            srcInfo = fromMaybe "(stdin)" inplace+                return (ImportAlt (Embed frozenMissing) (Embed thawedImport))+        cache expression_ =+            return expression_++    let uncache+            (ImportAlt+                (Core.shallowDenote -> Embed+                    Import{ importHashed = ImportHashed { hash = Just expectedHash, importType = Missing } }+                )+                (Core.shallowDenote -> Embed+                    import_@Import{ importHashed = ImportHashed{ hash = Nothing } }+                )+            ) = Embed+                (import_+                    { importHashed = (importHashed import_)+                        { hash = Just expectedHash+                        }+                    }+                )+        uncache expression_ = expression_++    let simplify (ImportAlt (Core.shallowDenote -> Embed import1) (Core.shallowDenote -> Embed import2))+            | import1 == import2 = Embed import1+        simplify expression_ = expression_++    transformOf Core.subExpressions simplify <$> case intent of+        Secure ->+            traverse freezeFunction (transformOf Core.subExpressions uncache expression)+        Cache  ->+            transformMOf Core.subExpressions cache expression++-- https://github.com/dhall-lang/dhall-haskell/issues/2347+toMissing :: Import -> Import+toMissing import_ =+    import_ { importHashed = (importHashed import_) { importType = Missing } }
− src/Dhall/Hash.hs
@@ -1,44 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}---- | This module contains the implementation of the @dhall hash@ subcommand--module Dhall.Hash-    ( -- * Hash-      hash-    ) where--import Dhall.Binary (StandardVersion)-import Dhall.Parser (exprFromText)-import Dhall.Import (hashExpressionToCode, standardVersion)-import Lens.Family (set)--import qualified Control.Monad.Trans.State.Strict as State-import qualified Control.Exception-import qualified Dhall.Core-import qualified Dhall.Import-import qualified Dhall.TypeCheck-import qualified Data.Text.IO---- | Implementation of the @dhall hash@ subcommand-hash :: StandardVersion -> IO ()-hash _standardVersion = do-    inText <- Data.Text.IO.getContents--    parsedExpression <- case exprFromText "(stdin)" inText of-        Left  exception        -> Control.Exception.throwIO exception-        Right parsedExpression -> return parsedExpression--    let status =-            set standardVersion _standardVersion (Dhall.Import.emptyStatus ".")--    resolvedExpression <- State.evalStateT (Dhall.Import.loadWith parsedExpression) status--    case Dhall.TypeCheck.typeOf resolvedExpression of-        Left  exception -> Control.Exception.throwIO exception-        Right _         -> return ()--    let normalizedExpression =-            Dhall.Core.alphaNormalize (Dhall.Core.normalize resolvedExpression)--    Data.Text.IO.putStrLn-        (hashExpressionToCode _standardVersion normalizedExpression)
src/Dhall/Import.hs view
@@ -1,988 +1,1401 @@-{-# LANGUAGE CPP                 #-}-{-# LANGUAGE DeriveAnyClass      #-}-{-# LANGUAGE DeriveDataTypeable  #-}-{-# LANGUAGE NamedFieldPuns      #-}-{-# LANGUAGE OverloadedStrings   #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE RankNTypes          #-}-{-# LANGUAGE RecordWildCards     #-}-{-# OPTIONS_GHC -Wall #-}--{-| Dhall lets you import external expressions located either in local files or-    hosted on network endpoints.--    To import a local file as an expression, just insert the path to the file,-    prepending a @./@ if the path is relative to the current directory.  For-    example, if you create a file named @id@ with the following contents:--    > $ cat id-    > λ(a : Type) → λ(x : a) → x--    Then you can use the file directly within a @dhall@ program just by-    referencing the file's path:--    > $ dhall-    > ./id Bool True-    > <Ctrl-D>-    > Bool-    >-    > True--    Imported expressions may contain imports of their own, too, which will-    continue to be resolved.  However, Dhall will prevent cyclic imports.  For-    example, if you had these two files:--    > $ cat foo-    > ./bar--    > $ cat bar-    > ./foo--    ... Dhall would throw the following exception if you tried to import @foo@:--    > $ dhall-    > ./foo-    > ^D-    > ↳ ./foo-    >   ↳ ./bar-    >-    > Cyclic import: ./foo--    You can also import expressions hosted on network endpoints.  Just use the-    URL--    > http://host[:port]/path--    The compiler expects the downloaded expressions to be in the same format-    as local files, specifically UTF8-encoded source code text.--    For example, if our @id@ expression were hosted at @http://example.com/id@,-    then we would embed the expression within our code using:--    > http://example.com/id--    You can also import expressions stored within environment variables using-    @env:NAME@, where @NAME@ is the name of the environment variable.  For-    example:--    > $ export FOO=1-    > $ export BAR='"Hi"'-    > $ export BAZ='λ(x : Bool) → x == False'-    > $ dhall <<< "{ foo = env:FOO , bar = env:BAR , baz = env:BAZ }"-    > { bar : Text, baz : ∀(x : Bool) → Bool, foo : Integer }-    >-    > { bar = "Hi", baz = λ(x : Bool) → x == False, foo = 1 }--    If you wish to import the raw contents of an impoert as @Text@ then add-    @as Text@ to the end of the import:--    > $ dhall <<< "http://example.com as Text"-    > Text-    >-    > "<!doctype html>\n<html>\n<head>\n    <title>Example Domain</title>\n\n    <meta-    >  charset=\"utf-8\" />\n    <meta http-equiv=\"Content-type\" content=\"text/html-    > ; charset=utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-width,-    > initial-scale=1\" />\n    <style type=\"text/css\">\n    body {\n        backgro-    > und-color: #f0f0f2;\n        margin: 0;\n        padding: 0;\n        font-famil-    > y: \"Open Sans\", \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n        \n-    >    }\n    div {\n        width: 600px;\n        margin: 5em auto;\n        paddi-    > ng: 50px;\n        background-color: #fff;\n        border-radius: 1em;\n    }\n-    >     a:link, a:visited {\n        color: #38488f;\n        text-decoration: none;-    > \n    }\n    @media (max-width: 700px) {\n        body {\n            background-    > -color: #fff;\n        }\n        div {\n            width: auto;\n            m-    > argin: 0 auto;\n            border-radius: 0;\n            padding: 1em;\n-    >   }\n    }\n    </style>    \n</head>\n\n<body>\n<div>\n    <h1>Example Domain</-    > h1>\n    <p>This domain is established to be used for illustrative examples in d-    > ocuments. You may use this\n    domain in examples without prior coordination or-    >  asking for permission.</p>\n    <p><a href=\"http://www.iana.org/domains/exampl-    > e\">More information...</a></p>\n</div>\n</body>\n</html>\n"--}--module Dhall.Import (-    -- * Import-      exprFromImport-    , exprToImport-    , load-    , loadWith-    , hashExpression-    , hashExpressionToCode-    , assertNoImports-    , Status-    , emptyStatus-    , stack-    , cache-    , manager-    , standardVersion-    , normalizer-    , startingContext-    , resolver-    , cacher-    , Cycle(..)-    , ReferentiallyOpaque(..)-    , Imported(..)-    , ImportResolutionDisabled(..)-    , PrettyHttpException(..)-    , MissingFile(..)-    , MissingEnvironmentVariable(..)-    , MissingImports(..)-    , HashMismatch(..)-    ) where--import Control.Applicative (Alternative(..))-import Codec.CBOR.Term (Term(..))-import Control.Exception (Exception, SomeException, throwIO, toException)-import Control.Monad (guard)-import Control.Monad.Catch (throwM, MonadCatch(catch), catches, Handler(..))-import Control.Monad.IO.Class (MonadIO(..))-import Control.Monad.Trans.State.Strict (StateT)-import Crypto.Hash (SHA256)-import Data.CaseInsensitive (CI)-import Data.List.NonEmpty (NonEmpty(..))-import Data.Semigroup (Semigroup(..))-import Data.Text (Text)-#if MIN_VERSION_base(4,8,0)-#else-import Data.Traversable (traverse)-#endif-import Data.Typeable (Typeable)-import System.FilePath ((</>))-import Dhall.Binary (StandardVersion(..))-import Dhall.Core-    ( Expr(..)-    , Binding(..)-    , Chunks(..)-    , Directory(..)-    , File(..)-    , FilePrefix(..)-    , ImportHashed(..)-    , ImportType(..)-    , ImportMode(..)-    , Import(..)-    , URL(..)-    )-#ifdef MIN_VERSION_http_client-import Dhall.Import.HTTP-#endif-import Dhall.Import.Types-import Text.Dot ((.->.), userNodeId)--import Dhall.Parser (Parser(..), ParseError(..), Src(..), SourcedException(..))-import Dhall.TypeCheck (X(..))-import Lens.Family.State.Strict (zoom)--import qualified Codec.Serialise-import qualified Control.Monad.Trans.Maybe        as Maybe-import qualified Control.Monad.Trans.State.Strict as State-import qualified Crypto.Hash-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.Map.Strict                  as Map-import qualified Data.Text.Encoding-import qualified Data.Text                        as Text-import qualified Data.Text.IO-import qualified Dhall.Binary-import qualified Dhall.Core-import qualified Dhall.Map-import qualified Dhall.Parser-import qualified Dhall.Pretty.Internal-import qualified Dhall.TypeCheck-import qualified System.Environment-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---- | An import failed because of a cycle in the import graph-newtype Cycle = Cycle-    { cyclicImport :: Import  -- ^ The offending cyclic import-    }-  deriving (Typeable)--instance Exception Cycle--instance Show Cycle where-    show (Cycle import_) =-        "\nCyclic import: " ++ Dhall.Pretty.Internal.prettyToString import_--{-| Dhall tries to ensure that all expressions hosted on network endpoints are-    weakly referentially transparent, meaning roughly that any two clients will-    compile the exact same result given the same URL.--    To be precise, a strong interpretaton of referential transparency means that-    if you compiled a URL you could replace the expression hosted at that URL-    with the compiled result.  Let's call this \"static linking\".  Dhall (very-    intentionally) does not satisfy this stronger interpretation of referential-    transparency since \"statically linking\" an expression (i.e. permanently-    resolving all imports) means that the expression will no longer update if-    its dependencies change.--    In general, either interpretation of referential transparency is not-    enforceable in a networked context since one can easily violate referential-    transparency with a custom DNS, but Dhall can still try to guard against-    common unintentional violations.  To do this, Dhall enforces that a-    non-local import may not reference a local import.--    Local imports are defined as:--    * A file--    * A URL with a host of @localhost@ or @127.0.0.1@--    All other imports are defined to be non-local--}-newtype ReferentiallyOpaque = ReferentiallyOpaque-    { opaqueImport :: Import  -- ^ The offending opaque import-    } deriving (Typeable)--instance Exception ReferentiallyOpaque--instance Show ReferentiallyOpaque where-    show (ReferentiallyOpaque import_) =-        "\nReferentially opaque import: " ++ Dhall.Pretty.Internal.prettyToString import_---- | Extend another exception with the current import stack-data Imported e = Imported-    { importStack :: NonEmpty Import -- ^ Imports resolved so far, in reverse order-    , nested      :: e               -- ^ The nested exception-    } deriving (Typeable)--instance Exception e => Exception (Imported e)--instance Show e => Show (Imported e) where-    show (Imported canonicalizedImports e) =-           concat (zipWith indent [0..] toDisplay)-        ++ "\n"-        ++ show e-      where-        indent n import_ =-            "\n" ++ replicate (2 * n) ' ' ++ "↳ " ++ Dhall.Pretty.Internal.prettyToString import_--        canonical = NonEmpty.toList canonicalizedImports--        -- Tthe final (outermost) import is fake to establish the base-        -- directory. Also, we need outermost-first.-        toDisplay = drop 1 (reverse canonical)---- | Exception thrown when an imported file is missing-data MissingFile = MissingFile FilePath-    deriving (Typeable)--instance Exception MissingFile--instance Show MissingFile where-    show (MissingFile path) =-            "\n"-        <>  "\ESC[1;31mError\ESC[0m: Missing file "-        <>  path---- | Exception thrown when an environment variable is missing-newtype MissingEnvironmentVariable = MissingEnvironmentVariable { name :: Text }-    deriving (Typeable)--instance Exception MissingEnvironmentVariable--instance Show MissingEnvironmentVariable where-    show (MissingEnvironmentVariable {..}) =-            "\n"-        <>  "\ESC[1;31mError\ESC[0m: Missing environment variable\n"-        <>  "\n"-        <>  "↳ " <> Text.unpack name---- | List of Exceptions we encounter while resolving Import Alternatives-newtype MissingImports = MissingImports [SomeException]--instance Exception MissingImports--instance Show MissingImports where-    show (MissingImports []) =-            "\n"-        <>  "\ESC[1;31mError\ESC[0m: No valid imports"-    show (MissingImports [e]) = show e-    show (MissingImports es) =-            "\n"-        <>  "\ESC[1;31mError\ESC[0m: Failed to resolve imports. Error list:"-        <>  "\n"-        <>  concatMap (\e -> "\n" <> show e <> "\n") es--throwMissingImport :: (MonadCatch m, Exception e) => e -> m a-throwMissingImport e = throwM (MissingImports [toException e])---- | Exception thrown when a HTTP url is imported but dhall was built without--- the @with-http@ Cabal flag.-data CannotImportHTTPURL =-    CannotImportHTTPURL-        String-        (Maybe [(CI Data.ByteString.ByteString, Data.ByteString.ByteString)])-    deriving (Typeable)--instance Exception CannotImportHTTPURL--instance Show CannotImportHTTPURL where-    show (CannotImportHTTPURL url _mheaders) =-            "\n"-        <>  "\ESC[1;31mError\ESC[0m: Cannot import HTTP URL.\n"-        <>  "\n"-        <>  "Dhall was compiled without the 'with-http' flag.\n"-        <>  "\n"-        <>  "The requested URL was: "-        <>  url-        <>  "\n"--{-|-> canonicalize . canonicalize = canonicalize--> canonicalize (a <> b) = canonicalize a <> canonicalize b--}-class Semigroup path => Canonicalize path where-    canonicalize :: path -> path---- |--- >>> canonicalize (Directory {components = ["..",".."]})--- Directory {components = ["..",".."]}-instance Canonicalize Directory where-    canonicalize (Directory []) = Directory []--    canonicalize (Directory ("." : components₀)) =-        canonicalize (Directory components₀)--    canonicalize (Directory (".." : components₀)) =-        case canonicalize (Directory components₀) of-            Directory [] ->-                Directory [ ".." ]-            Directory (".." : components₁) ->-                Directory (".." : ".." : components₁)-            Directory (_    : components₁) ->-                Directory components₁--    canonicalize (Directory (component : components₀)) =-        Directory (component : components₁)-      where-        Directory components₁ = canonicalize (Directory components₀)--instance Canonicalize File where-    canonicalize (File { directory, .. }) =-        File { directory = canonicalize directory, .. }--instance Canonicalize ImportType where-    canonicalize (Local prefix file) =-        Local prefix (canonicalize file)--    canonicalize (Remote (URL {..})) =-        Remote (URL { path = canonicalize path, headers = fmap (fmap canonicalize) headers, ..})--    canonicalize (Env name) =-        Env name--    canonicalize Missing =-        Missing--instance Canonicalize ImportHashed where-    canonicalize (ImportHashed hash importType) =-        ImportHashed hash (canonicalize importType)--instance Canonicalize Import where-    canonicalize (Import importHashed importMode) =-        Import (canonicalize importHashed) importMode--toHeaders-  :: Expr s a-  -> Maybe [(CI Data.ByteString.ByteString, Data.ByteString.ByteString)]-toHeaders (ListLit _ hs) = do-    hs' <- mapM toHeader hs-    return (Data.Foldable.toList hs')-toHeaders  _             = do-    empty--toHeader-  :: Expr s a-  -> Maybe (CI Data.ByteString.ByteString, Data.ByteString.ByteString)-toHeader (RecordLit m) = do-    TextLit (Chunks [] keyText  ) <- Dhall.Map.lookup "header" m-    TextLit (Chunks [] valueText) <- Dhall.Map.lookup "value"  m-    let keyBytes   = Data.Text.Encoding.encodeUtf8 keyText-    let valueBytes = Data.Text.Encoding.encodeUtf8 valueText-    return (Data.CaseInsensitive.mk keyBytes, valueBytes)-toHeader _ = do-    empty----- | Exception thrown when an integrity check fails-data HashMismatch = HashMismatch-    { expectedHash :: Crypto.Hash.Digest SHA256-    , actualHash   :: Crypto.Hash.Digest SHA256-    } deriving (Typeable)--instance Exception HashMismatch--instance Show HashMismatch where-    show (HashMismatch {..}) =-            "\n"-        <>  "\ESC[1;31mError\ESC[0m: Import integrity check failed\n"-        <>  "\n"-        <>  "Expected hash:\n"-        <>  "\n"-        <>  "↳ " <> show expectedHash <> "\n"-        <>  "\n"-        <>  "Actual hash:\n"-        <>  "\n"-        <>  "↳ " <> show actualHash <> "\n"--localToPath :: MonadIO io => FilePrefix -> File -> io FilePath-localToPath prefix file_ = liftIO $ do-    let File {..} = file_--    let Directory {..} = directory--    prefixPath <- case prefix of-        Home -> do-            Directory.getHomeDirectory--        Absolute -> do-            return "/"--        Parent -> do-            pwd <- Directory.getCurrentDirectory-            return (FilePath.takeDirectory pwd)--        Here -> do-            Directory.getCurrentDirectory--    let cs = map Text.unpack (file : components)--    let cons component dir = dir </> component--    return (foldr cons prefixPath cs)---- | Parse an expression from a `Import` containing a Dhall program-exprFromImport :: Import -> StateT (Status IO) IO Resolved-exprFromImport here@(Import {..}) = do-    let ImportHashed {..} = importHashed--    Status {..} <- State.get--    result <- Maybe.runMaybeT $ do-        Just expectedHash <- return hash-        cacheFile         <- getCacheFile expectedHash-        True              <- liftIO (Directory.doesFileExist cacheFile)--        bytesStrict <- liftIO (Data.ByteString.readFile cacheFile)--        let actualHash = Crypto.Hash.hash bytesStrict--        if expectedHash == actualHash-            then return ()-            else throwMissingImport (Imported _stack (HashMismatch {..}))--        let bytesLazy = Data.ByteString.Lazy.fromStrict bytesStrict--        term <- Dhall.Core.throws (Codec.Serialise.deserialiseOrFail bytesLazy)--        Dhall.Core.throws (Dhall.Binary.decodeExpression term)--    case result of-        Just resolvedExpression -> do-            let newImport = here--            return (Resolved {..})-        Nothing -> do-            exprFromUncachedImport here--{-| Save an expression to the specified `Import`--    Currently this only works for cached imports and ignores other types of-    imports, but could conceivably work for uncached imports in the future--    The main reason for this more general type is for symmetry with-    `exprFromImport` and to support doing more clever things in the future,-    like doing \"the right thing\" for uncached imports (i.e. exporting-    environment variables or creating files)--}-exprToImport :: Import -> Expr Src X -> StateT (Status IO) IO ()-exprToImport here expression = do-    Status {..} <- State.get--    let Import {..} = here--    let ImportHashed {..} = importHashed--    _ <- Maybe.runMaybeT $ do-        Just expectedHash  <- return hash-        cacheFile          <- getCacheFile expectedHash--        _ <- Dhall.Core.throws (Dhall.TypeCheck.typeWith _startingContext expression)--        let normalizedExpression =-                Dhall.Core.alphaNormalize-                    (Dhall.Core.normalizeWith-                        _normalizer-                        expression-                    )--        let check version = do-                let bytes = encodeExpression version normalizedExpression--                let actualHash = Crypto.Hash.hash bytes--                guard (expectedHash == actualHash)--                liftIO (Data.ByteString.writeFile cacheFile bytes)--        let fallback = do-                let actualHash = hashExpression NoVersion normalizedExpression--                throwMissingImport (Imported _stack (HashMismatch {..}))--        Data.Foldable.asum (map check [ minBound .. maxBound ]) <|> fallback--    return ()--getCacheFile-    :: (Alternative m, MonadIO m) => Crypto.Hash.Digest SHA256 -> m FilePath-getCacheFile hash = do-    let assertDirectory directory = do-            let private = transform Directory.emptyPermissions-                  where-                    transform =-                            Directory.setOwnerReadable   True-                        .   Directory.setOwnerWritable   True-                        .   Directory.setOwnerSearchable True--            let accessible path =-                       Directory.readable   path-                    && Directory.writable   path-                    && Directory.searchable path--            directoryExists <- liftIO (Directory.doesDirectoryExist directory)--            if directoryExists-                then do-                    permissions <- liftIO (Directory.getPermissions directory)--                    guard (accessible permissions)--                else do-                    assertDirectory (FilePath.takeDirectory directory)--                    liftIO (Directory.createDirectory directory)--                    liftIO (Directory.setPermissions directory private)--    cacheDirectory <- getCacheDirectory--    let dhallDirectory = cacheDirectory </> "dhall"--    assertDirectory dhallDirectory--    let cacheFile = dhallDirectory </> show hash--    return cacheFile--getCacheDirectory :: (Alternative m, MonadIO m) => m FilePath-getCacheDirectory = alternative₀ <|> alternative₁-  where-    alternative₀ = do-        maybeXDGCacheHome <- do-          liftIO (System.Environment.lookupEnv "XDG_CACHE_HOME")--        case maybeXDGCacheHome of-            Just xdgCacheHome -> return xdgCacheHome-            Nothing           -> empty--    alternative₁ = do-        maybeHomeDirectory <- liftIO (System.Environment.lookupEnv "HOME")--        case maybeHomeDirectory of-            Just homeDirectory -> return (homeDirectory </> ".cache")-            Nothing            -> empty--exprFromUncachedImport :: Import -> StateT (Status IO) IO Resolved-exprFromUncachedImport import_@(Import {..}) = do-    let ImportHashed {..} = importHashed--    (path, text, newImport) <- case importType of-        Local prefix file -> liftIO $ do-            path   <- localToPath prefix file-            exists <- Directory.doesFileExist path--            if exists-                then return ()-                else throwMissingImport (MissingFile path)--            text <- Data.Text.IO.readFile path--            return (path, text, import_)--        Remote url@URL { headers = maybeHeadersExpression } -> do-            maybeHeadersAndExpression <- case maybeHeadersExpression of-                Nothing -> do-                    return Nothing-                Just headersExpression -> do-                    expr <- loadWith headersExpression--                    let expected :: Expr Src X-                        expected =-                            App List-                                ( Record-                                    ( Dhall.Map.fromList-                                        [("header", Text), ("value", Text)]-                                    )-                                )-                    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 -> liftIO (throwIO err)-                        Right _  -> return ()--                    let expr' = Dhall.Core.normalize expr--                    case toHeaders expr' of-                        Just headers -> do-                            return (Just (headers, expr'))-                        Nothing      -> do-                            liftIO (throwIO InternalError)--#ifdef MIN_VERSION_http_client-            let maybeHeaders = fmap fst maybeHeadersAndExpression--            let newHeaders =-                    fmap (fmap absurd . snd) maybeHeadersAndExpression--            (path, text) <- fetchFromHttpUrl url maybeHeaders--            let newImport = Import-                    { importHashed = ImportHashed-                        { importType =-                            Remote (url { headers = newHeaders })-                        , ..-                        }-                    , ..-                    }--            return (path, text, newImport)-#else-            let urlString = Text.unpack (Dhall.Core.pretty url)--            liftIO (throwIO (CannotImportHTTPURL urlString mheaders))-#endif--        Env env -> liftIO $ do-            x <- System.Environment.lookupEnv (Text.unpack env)-            case x of-                Just string -> do-                    return (Text.unpack env, Text.pack string, import_)-                Nothing -> do-                    throwMissingImport (MissingEnvironmentVariable env)--        Missing -> liftIO $ do-            throwM (MissingImports [])--    case importMode of-        Code -> do-            let parser = unParser $ do-                    Text.Parser.Token.whiteSpace-                    r <- Dhall.Parser.expr-                    Text.Parser.Combinators.eof-                    return r--            case Text.Megaparsec.parse parser path text of-                Left errInfo -> do-                    liftIO (throwIO (ParseError errInfo text))-                Right resolvedExpression -> do-                    return (Resolved {..})--        RawText -> do-            let resolvedExpression = TextLit (Chunks [] text)--            return (Resolved {..})---- | Default starting `Status`, importing relative to the given directory.-emptyStatus :: FilePath -> Status IO-emptyStatus = emptyStatusWith exprFromImport exprToImport--{-| Generalized version of `load`--    You can configure the desired behavior through the initial `Status` that you-    supply--}-loadWith :: MonadCatch m => Expr Src Import -> StateT (Status m) m (Expr Src X)-loadWith expr₀ = case expr₀ of-  Embed import₀ -> do-    Status {..} <- State.get--    let parent = NonEmpty.head _stack--    let import₁ = parent <> import₀--    let child = canonicalize import₁--    let local (Import (ImportHashed _ (Remote  {})) _) = False-        local (Import (ImportHashed _ (Local   {})) _) = True-        local (Import (ImportHashed _ (Env     {})) _) = True-        local (Import (ImportHashed _ (Missing {})) _) = True--    let referentiallySane = not (local child) || local parent--    if referentiallySane-        then return ()-        else throwMissingImport (Imported _stack (ReferentiallyOpaque import₀))--    let _stack' = NonEmpty.cons child _stack--    expr <- if child `elem` _stack-        then throwMissingImport (Imported _stack (Cycle import₀))-        else do-            case Map.lookup child _cache of-                Just (childNode, expr) -> do-                    zoom dot . State.modify $ \getDot -> do-                        parentNode <- getDot--                        -- Add edge between parent and child-                        parentNode .->. childNode--                        -- Return parent NodeId-                        pure parentNode--                    pure expr-                Nothing        -> do-                    -- Here we have to match and unwrap the @MissingImports@-                    -- in a separate handler, otherwise we'd have it wrapped-                    -- in another @Imported@ when parsing a @missing@, because-                    -- we are representing it with an empty exception list-                    -- (which would not be empty if this would happen).-                    -- TODO: restructure the Exception hierarchy to prevent-                    -- this nesting from happening in the first place.-                    let handler₀-                            :: (MonadCatch m)-                            => MissingImports-                            -> StateT (Status m) m Resolved-                        handler₀ (MissingImports es) =-                          throwM-                            (MissingImports-                               (map-                                 (\e -> toException (Imported _stack' e))-                                 es-                               )-                             )--                        handler₁-                            :: (MonadCatch m)-                            => SomeException-                            -> StateT (Status m) m Resolved-                        handler₁ e =-                          throwMissingImport (Imported _stack' e)--                    -- This loads a \"dynamic\" expression (i.e. an expression-                    -- that might still contain imports)-                    let loadDynamic = _resolver child--                    Resolved {..} <- loadDynamic `catches` [ Handler handler₀, Handler handler₁ ]--                    let stackWithNewImport = NonEmpty.cons newImport _stack--                    let childNodeId = userNodeId _nextNodeId--                    -- Increment the next node id-                    zoom nextNodeId $ State.modify succ--                    -- Make current node the dot graph-                    zoom dot . State.put $ importNode childNodeId child--                    zoom stack (State.put stackWithNewImport)-                    expr'' <- loadWith resolvedExpression-                    zoom stack (State.put _stack)--                    zoom dot . State.modify $ \getSubDot -> do-                        parentNode <- _dot--                        -- Get current node back from sub-graph-                        childNode <- getSubDot--                        -- Add edge between parent and child-                        parentNode .->. childNode--                        -- Return parent NodeId-                        pure parentNode--                    _cacher child expr''--                    -- Type-check expressions here for three separate reasons:-                    ---                    --  * to verify that they are closed-                    --  * to catch type errors as early in the import process-                    --    as possible-                    --  * to avoid normalizing ill-typed expressions that need-                    --    to be hashed-                    ---                    -- There is no need to check expressions that have been-                    -- cached, since they have already been checked-                    expr''' <- case Dhall.TypeCheck.typeWith _startingContext expr'' of-                        Left  err -> throwM (Imported _stack' err)-                        Right _   -> return (Dhall.Core.normalizeWith _normalizer expr'')-                    zoom cache (State.modify' (Map.insert child (childNodeId, expr''')))-                    return expr'''--    case hash (importHashed import₀) of-        Nothing -> do-            return ()-        Just expectedHash -> do-            let matches version =-                    let actualHash =-                            hashExpression version (Dhall.Core.alphaNormalize expr)--                    in  expectedHash == actualHash--            if any matches [ minBound .. maxBound ]-                then return ()-                else do-                    let actualHash =-                            hashExpression NoVersion (Dhall.Core.alphaNormalize expr)--                    throwMissingImport (Imported _stack' (HashMismatch {..}))--    return expr-  ImportAlt a b -> loadWith a `catch` handler₀-    where-      handler₀ (SourcedException (Src begin _ text₀) (MissingImports es₀)) =-          loadWith b `catch` handler₁-        where-          handler₁ (SourcedException (Src _ end text₁) (MissingImports es₁)) =-              throwM (SourcedException (Src begin end text₂) (MissingImports (es₀ ++ es₁)))-            where-              text₂ = text₀ <> " ? " <> text₁--  Const a              -> pure (Const a)-  Var a                -> pure (Var a)-  Lam a b c            -> Lam <$> pure a <*> loadWith b <*> loadWith c-  Pi a b c             -> Pi <$> pure a <*> loadWith b <*> loadWith c-  App a b              -> App <$> loadWith a <*> loadWith b-  Let as b             -> Let <$> traverse f as <*> loadWith b-    where-      f (Binding c d e) = Binding c <$> traverse loadWith d <*> loadWith e-  Annot a b            -> Annot <$> loadWith a <*> loadWith b-  Bool                 -> pure Bool-  BoolLit a            -> pure (BoolLit a)-  BoolAnd a b          -> BoolAnd <$> loadWith a <*> loadWith b-  BoolOr a b           -> BoolOr <$> loadWith a <*> loadWith b-  BoolEQ a b           -> BoolEQ <$> loadWith a <*> loadWith b-  BoolNE a b           -> BoolNE <$> loadWith a <*> loadWith b-  BoolIf a b c         -> BoolIf <$> loadWith a <*> loadWith b <*> loadWith c-  Natural              -> pure Natural-  NaturalLit a         -> pure (NaturalLit a)-  NaturalFold          -> pure NaturalFold-  NaturalBuild         -> pure NaturalBuild-  NaturalIsZero        -> pure NaturalIsZero-  NaturalEven          -> pure NaturalEven-  NaturalOdd           -> pure NaturalOdd-  NaturalToInteger     -> pure NaturalToInteger-  NaturalShow          -> pure NaturalShow-  NaturalPlus a b      -> NaturalPlus <$> loadWith a <*> loadWith b-  NaturalTimes a b     -> NaturalTimes <$> loadWith a <*> loadWith b-  Integer              -> pure Integer-  IntegerLit a         -> pure (IntegerLit a)-  IntegerShow          -> pure IntegerShow-  IntegerToDouble      -> pure IntegerToDouble-  Double               -> pure Double-  DoubleLit a          -> pure (DoubleLit a)-  DoubleShow           -> pure DoubleShow-  Text                 -> pure Text-  TextLit (Chunks a b) -> fmap TextLit (Chunks <$> mapM (mapM loadWith) a <*> pure b)-  TextAppend a b       -> TextAppend <$> loadWith a <*> loadWith b-  TextShow             -> pure TextShow-  List                 -> pure List-  ListLit a b          -> ListLit <$> mapM loadWith a <*> mapM loadWith b-  ListAppend a b       -> ListAppend <$> loadWith a <*> loadWith b-  ListBuild            -> pure ListBuild-  ListFold             -> pure ListFold-  ListLength           -> pure ListLength-  ListHead             -> pure ListHead-  ListLast             -> pure ListLast-  ListIndexed          -> pure ListIndexed-  ListReverse          -> pure ListReverse-  Optional             -> pure Optional-  None                 -> pure None-  Some a               -> Some <$> loadWith a-  OptionalLit a b      -> OptionalLit <$> loadWith a <*> mapM loadWith b-  OptionalFold         -> pure OptionalFold-  OptionalBuild        -> pure OptionalBuild-  Record a             -> Record <$> mapM loadWith a-  RecordLit a          -> RecordLit <$> mapM loadWith a-  Union a              -> Union <$> mapM (mapM loadWith) a-  UnionLit a b c       -> UnionLit <$> pure a <*> loadWith b <*> mapM (mapM loadWith) c-  Combine a b          -> Combine <$> loadWith a <*> loadWith b-  CombineTypes a b     -> CombineTypes <$> loadWith a <*> loadWith b-  Prefer a b           -> Prefer <$> loadWith a <*> loadWith b-  Merge a b c          -> Merge <$> loadWith a <*> loadWith b <*> mapM loadWith c-  Field a b            -> Field <$> loadWith a <*> pure b-  Project a b          -> Project <$> loadWith a <*> mapM loadWith b-  Note a b             -> do-      let handler e = throwM (SourcedException a (e :: MissingImports))--      (Note <$> pure a <*> loadWith b) `catch` handler---- | Resolve all imports within an expression-load :: Expr Src Import -> IO (Expr Src X)-load expression = State.evalStateT (loadWith expression) (emptyStatus ".")--encodeExpression-    :: forall s-    .  StandardVersion-    -- ^ `Nothing` means to encode without the version tag-    -> Expr s X-    -> Data.ByteString.ByteString-encodeExpression _standardVersion expression = bytesStrict-  where-    intermediateExpression :: Expr s Import-    intermediateExpression = fmap absurd expression--    term :: Term-    term = Dhall.Binary.encode intermediateExpression--    taggedTerm :: Term-    taggedTerm =-        case _standardVersion of-            NoVersion -> term-            s         -> TList [ TString v, term ]-              where-                v = Dhall.Binary.renderStandardVersion s--    bytesLazy = Codec.Serialise.serialise taggedTerm--    bytesStrict = Data.ByteString.Lazy.toStrict bytesLazy---- | Hash a fully resolved expression-hashExpression-    :: StandardVersion -> Expr s X -> (Crypto.Hash.Digest SHA256)-hashExpression _standardVersion expression =-    Crypto.Hash.hash (encodeExpression _standardVersion expression)--{-| Convenience utility to hash a fully resolved expression and return the-    base-16 encoded hash with the @sha256:@ prefix--    In other words, the output of this function can be pasted into Dhall-    source code to add an integrity check to an import--}-hashExpressionToCode :: StandardVersion -> Expr s X -> Text-hashExpressionToCode _standardVersion expr =-    "sha256:" <> Text.pack (show (hashExpression _standardVersion expr))---- | A call to `assertNoImports` failed because there was at least one import-data ImportResolutionDisabled = ImportResolutionDisabled deriving (Exception)--instance Show ImportResolutionDisabled where-    show _ = "\nImport resolution is disabled"---- | Assert than an expression is import-free-assertNoImports :: MonadIO io => Expr Src Import -> io (Expr Src X)-assertNoImports expression =-    Dhall.Core.throws (traverse (\_ -> Left ImportResolutionDisabled) expression)+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE CPP                 #-}+{-# LANGUAGE DeriveAnyClass      #-}+{-# LANGUAGE DeriveDataTypeable  #-}+{-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE NamedFieldPuns      #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE RankNTypes          #-}+{-# LANGUAGE RecordWildCards     #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-}++{-# OPTIONS_GHC -Wall #-}++{-| Dhall lets you import external expressions located either in local files or+    hosted on network endpoints.++    To import a local file as an expression, just insert the path to the file,+    prepending a @./@ if the path is relative to the current directory.  For+    example, if you create a file named @id@ with the following contents:++    > $ cat id+    > λ(a : Type) → λ(x : a) → x++    Then you can use the file directly within a @dhall@ program just by+    referencing the file's path:++    > $ dhall+    > ./id Bool True+    > <Ctrl-D>+    > Bool+    >+    > True++    Imported expressions may contain imports of their own, too, which will+    continue to be resolved.  However, Dhall will prevent cyclic imports.  For+    example, if you had these two files:++    > $ cat foo+    > ./bar++    > $ cat bar+    > ./foo++    ... Dhall would throw the following exception if you tried to import @foo@:++    > $ dhall+    > ./foo+    > ^D+    > ↳ ./foo+    >   ↳ ./bar+    >+    > Cyclic import: ./foo++    You can also import expressions hosted on network endpoints.  Just use the+    URL++    > http://host[:port]/path++    The compiler expects the downloaded expressions to be in the same format+    as local files, specifically UTF8-encoded source code text.++    For example, if our @id@ expression were hosted at @http://example.com/id@,+    then we would embed the expression within our code using:++    > http://example.com/id++    You can also import expressions stored within environment variables using+    @env:NAME@, where @NAME@ is the name of the environment variable.  For+    example:++    > $ export FOO=1+    > $ export BAR='"Hi"'+    > $ export BAZ='λ(x : Bool) → x == False'+    > $ dhall <<< "{ foo = env:FOO , bar = env:BAR , baz = env:BAZ }"+    > { bar : Text, baz : ∀(x : Bool) → Bool, foo : Integer }+    >+    > { bar = "Hi", baz = λ(x : Bool) → x == False, foo = 1 }++    If you wish to import the raw contents of an impoert as @Text@ then add+    @as Text@ to the end of the import:++    > $ dhall <<< "http://example.com as Text"+    > Text+    >+    > "<!doctype html>\n<html>\n<head>\n    <title>Example Domain</title>\n\n    <meta+    >  charset=\"utf-8\" />\n    <meta http-equiv=\"Content-type\" content=\"text/html+    > ; charset=utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-width,+    > initial-scale=1\" />\n    <style type=\"text/css\">\n    body {\n        backgro+    > und-color: #f0f0f2;\n        margin: 0;\n        padding: 0;\n        font-famil+    > y: \"Open Sans\", \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n        \n+    >    }\n    div {\n        width: 600px;\n        margin: 5em auto;\n        paddi+    > ng: 50px;\n        background-color: #fff;\n        border-radius: 1em;\n    }\n+    >     a:link, a:visited {\n        color: #38488f;\n        text-decoration: none;+    > \n    }\n    @media (max-width: 700px) {\n        body {\n            background+    > -color: #fff;\n        }\n        div {\n            width: auto;\n            m+    > argin: 0 auto;\n            border-radius: 0;\n            padding: 1em;\n+    >   }\n    }\n    </style>    \n</head>\n\n<body>\n<div>\n    <h1>Example Domain</+    > h1>\n    <p>This domain is established to be used for illustrative examples in d+    > ocuments. You may use this\n    domain in examples without prior coordination or+    >  asking for permission.</p>\n    <p><a href=\"http://www.iana.org/domains/exampl+    > e\">More information...</a></p>\n</div>\n</body>\n</html>\n"+-}++module Dhall.Import (+    -- * Import+      load+    , loadWithManager+    , loadRelativeTo+    , loadWithStatus+    , loadWith+    , localToPath+    , hashExpression+    , hashExpressionToCode+    , writeExpressionToSemanticCache+    , assertNoImports+    , Manager+    , defaultNewManager+    , CacheWarning(..)+    , Status(..)+    , SemanticCacheMode(..)+    , Chained+    , chainedImport+    , chainedFromLocalHere+    , chainedChangeMode+    , emptyStatus+    , emptyStatusWithManager+    , envOriginHeaders+    , makeEmptyStatus+    , remoteStatus+    , remoteStatusWithManager+    , fetchRemote+    , stack+    , cache+    , Depends(..)+    , graph+    , remote+    , toHeaders+    , substitutions+    , normalizer+    , startingContext+    , chainImport+    , dependencyToFile+    , ImportSemantics+    , HTTPHeader+    , Cycle(..)+    , ReferentiallyOpaque(..)+    , Imported(..)+    , ImportResolutionDisabled(..)+    , PrettyHttpException(..)+    , MissingFile(..)+    , MissingEnvironmentVariable(..)+    , MissingImports(..)+    , HashMismatch(..)+    ) where++import Control.Applicative        (Alternative (..))+import Control.Exception+    ( Exception+    , IOException+    , SomeException+    , toException+    )+import Control.Monad.Catch        (MonadCatch (catch), handle, throwM)+import Control.Monad.IO.Class     (MonadIO (..))+import Control.Monad.Morph        (hoist)+import Control.Monad.State.Strict (MonadState, StateT)+import Data.ByteString            (ByteString)+import Data.List.NonEmpty         (NonEmpty (..), nonEmpty)+import Data.Maybe                 (fromMaybe)+import Data.Text                  (Text)+import Data.Typeable              (Typeable)+import Data.Void                  (Void, absurd)+import Dhall.TypeCheck            (TypeError)+import Dhall.Util                 (printWarning)++import Dhall.Syntax+    ( Chunks (..)+    , Directory (..)+    , Expr (..)+    , File (..)+    , FilePrefix (..)+    , Import (..)+    , ImportHashed (..)+    , ImportMode (..)+    , ImportType (..)+    , URL (..)+    , bindingExprs+    , functionBindingExprs+    , recordFieldExprs+    )++import System.FilePath ((</>))+import Text.Megaparsec (SourcePos (SourcePos), mkPos)++#ifdef WITH_HTTP+import Dhall.Import.HTTP+#endif+import Dhall.Import.Headers+    ( normalizeHeaders+    , originHeadersTypeExpr+    , toHeaders+    , toOriginHeaders+    )+import Dhall.Import.Types++import Dhall.Parser+    ( ParseError (..)+    , Parser (..)+    , SourcedException (..)+    , Src (..)+    )+import Lens.Micro.Mtl (zoom)++import qualified Codec.CBOR.Write                            as Write+import qualified Codec.Serialise+import qualified Control.Exception                           as Exception+import qualified Control.Monad.State.Strict                  as State+import qualified Control.Monad.Trans.Maybe                   as Maybe+import qualified Data.ByteString+import qualified Data.ByteString.Lazy+import qualified Data.List.NonEmpty                          as NonEmpty+import qualified Data.Maybe                                  as Maybe+import qualified Data.Text                                   as Text+import qualified Data.Text.Encoding                          as Encoding+import qualified Data.Text.IO+import qualified Dhall.Binary+import qualified Dhall.Core                                  as Core+import qualified Dhall.Crypto+import qualified Dhall.Map+import qualified Dhall.Parser+import qualified Dhall.Pretty.Internal+import qualified Dhall.Substitution+import qualified Dhall.Syntax                                as Syntax+import qualified Dhall.TypeCheck+import qualified System.AtomicWrite.Writer.ByteString.Binary as AtomicWrite.Binary+import qualified System.Directory                            as Directory+import qualified System.Environment+import qualified System.FilePath                             as FilePath+import qualified System.Info+import qualified System.IO+import qualified Text.Megaparsec+import qualified Text.Parser.Combinators+import qualified Text.Parser.Token++{- $setup++    >>> import Dhall.Syntax+-}++-- | An import failed because of a cycle in the import graph+newtype Cycle = Cycle+    { cyclicImport :: Import  -- ^ The offending cyclic import+    }+  deriving (Typeable)++instance Exception Cycle++instance Show Cycle where+    show (Cycle import_) =+        "\nCyclic import: " ++ Dhall.Pretty.Internal.prettyToString import_++{-| Dhall tries to ensure that all expressions hosted on network endpoints are+    weakly referentially transparent, meaning roughly that any two clients will+    compile the exact same result given the same URL.++    To be precise, a strong interpretaton of referential transparency means that+    if you compiled a URL you could replace the expression hosted at that URL+    with the compiled result.  Let's call this \"static linking\".  Dhall (very+    intentionally) does not satisfy this stronger interpretation of referential+    transparency since \"statically linking\" an expression (i.e. permanently+    resolving all imports) means that the expression will no longer update if+    its dependencies change.++    In general, either interpretation of referential transparency is not+    enforceable in a networked context since one can easily violate referential+    transparency with a custom DNS, but Dhall can still try to guard against+    common unintentional violations.  To do this, Dhall enforces that a+    non-local import may not reference a local import.++    Local imports are defined as:++    * A file++    * A URL with a host of @localhost@ or @127.0.0.1@++    All other imports are defined to be non-local+-}+newtype ReferentiallyOpaque = ReferentiallyOpaque+    { opaqueImport :: Import  -- ^ The offending opaque import+    } deriving (Typeable)++instance Exception ReferentiallyOpaque++instance Show ReferentiallyOpaque where+    show (ReferentiallyOpaque import_) =+        "\nLocal imports are not permitted from remote imports: " ++ Dhall.Pretty.Internal.prettyToString import_++-- | Extend another exception with the current import stack+data Imported e = Imported+    { importStack :: NonEmpty Chained  -- ^ Imports resolved so far, in reverse order+    , nested      :: e                 -- ^ The nested exception+    } deriving (Typeable)++instance Exception e => Exception (Imported e)++instance Show e => Show (Imported e) where+    show (Imported canonicalizedImports e) =+           concat (zipWith indent [0..] toDisplay)+        ++ "\n"+        ++ show e+      where+        indent n import_ =+            "\n" ++ replicate (2 * n) ' ' ++ "↳ " ++ Dhall.Pretty.Internal.prettyToString import_++        canonical = NonEmpty.toList canonicalizedImports++        -- Tthe final (outermost) import is fake to establish the base+        -- directory. Also, we need outermost-first.+        toDisplay = drop 1 (reverse canonical)++-- | Exception thrown when an imported file is missing+newtype MissingFile = MissingFile FilePath+    deriving (Typeable)++instance Exception MissingFile++instance Show MissingFile where+    show (MissingFile path) =+            "\n"+        <>  "\ESC[1;31mError\ESC[0m: Missing file "+        <>  path++-- | Exception thrown when an environment variable is missing+newtype MissingEnvironmentVariable = MissingEnvironmentVariable { name :: Text }+    deriving (Typeable)++instance Exception MissingEnvironmentVariable++instance Show MissingEnvironmentVariable where+    show MissingEnvironmentVariable{..} =+            "\n"+        <>  "\ESC[1;31mError\ESC[0m: Missing environment variable\n"+        <>  "\n"+        <>  "↳ " <> Text.unpack name++-- | List of Exceptions we encounter while resolving Import Alternatives+newtype MissingImports = MissingImports [SomeException]++instance Exception MissingImports++instance Show MissingImports where+    show (MissingImports []) =+            "\n"+        <>  "\ESC[1;31mError\ESC[0m: No valid imports"+    show (MissingImports [e]) = show e+    show (MissingImports es) =+            "\n"+        <>  "\ESC[1;31mError\ESC[0m: Failed to resolve imports. Error list:"+        <>  "\n"+        <>  concatMap (\e -> "\n" <> show e <> "\n") es++throwMissingImport :: (MonadCatch m, Exception e) => e -> m a+throwMissingImport e = throwM (MissingImports [toException e])++-- | Exception thrown when a HTTP url is imported but dhall was built without+-- the @with-http@ Cabal flag.+data CannotImportHTTPURL =+    CannotImportHTTPURL+        String+        (Maybe [HTTPHeader])+    deriving (Typeable)++instance Exception CannotImportHTTPURL++instance Show CannotImportHTTPURL where+    show (CannotImportHTTPURL url _mheaders) =+            "\n"+        <>  "\ESC[1;31mError\ESC[0m: Cannot import HTTP URL.\n"+        <>  "\n"+        <>  "Dhall was compiled without the 'with-http' flag.\n"+        <>  "\n"+        <>  "The requested URL was: "+        <>  url+        <>  "\n"++{-|+> canonicalize . canonicalize = canonicalize++> canonicalize (a <> b) = canonicalize (canonicalize a <> canonicalize b)+-}+class Semigroup path => Canonicalize path where+    canonicalize :: path -> path++-- |+-- >>> canonicalize (Directory {components = ["..",".."]})+-- Directory {components = ["..",".."]}+instance Canonicalize Directory where+    canonicalize (Directory []) = Directory []++    canonicalize (Directory ("." : components₀)) =+        canonicalize (Directory components₀)++    canonicalize (Directory (".." : components₀)) =+        case canonicalize (Directory components₀) of+            Directory [] ->+                Directory [ ".." ]+            Directory (".." : components₁) ->+                Directory (".." : ".." : components₁)+            Directory (_    : components₁) ->+                Directory components₁++    canonicalize (Directory (component : components₀)) =+        Directory (component : components₁)+      where+        Directory components₁ = canonicalize (Directory components₀)++instance Canonicalize File where+    canonicalize (File { directory, .. }) =+        File { directory = canonicalize directory, .. }++instance Canonicalize ImportType where+    canonicalize (Local prefix file) =+        Local prefix (canonicalize file)++    canonicalize (Remote (URL {..})) =+        Remote (URL { path = canonicalize path, headers = fmap (fmap canonicalize) headers, ..})++    canonicalize (Env name) =+        Env name++    canonicalize Missing =+        Missing++instance Canonicalize ImportHashed where+    canonicalize (ImportHashed hash importType) =+        ImportHashed hash (canonicalize importType)++instance Canonicalize Import where+    canonicalize (Import importHashed importMode) =+        Import (canonicalize importHashed) importMode++-- | Exception thrown when an integrity check fails+data HashMismatch = HashMismatch+    { expectedHash :: Dhall.Crypto.SHA256Digest+    , actualHash   :: Dhall.Crypto.SHA256Digest+    } deriving (Typeable)++instance Exception HashMismatch++instance Show HashMismatch where+    show HashMismatch{..} =+            "\n"+        <>  "\ESC[1;31mError\ESC[0m: " <> makeHashMismatchMessage expectedHash actualHash++makeHashMismatchMessage :: Dhall.Crypto.SHA256Digest -> Dhall.Crypto.SHA256Digest -> String+makeHashMismatchMessage expectedHash actualHash =+    "Import integrity check failed\n"+        <>  "\n"+        <>  "Expected hash:\n"+        <>  "\n"+        <>  "↳ " <> show expectedHash <> "\n"+        <>  "\n"+        <>  "Actual hash:\n"+        <>  "\n"+        <>  "↳ " <> show actualHash <> "\n"++-- | Construct the file path corresponding to a local import. If the import is+--   _relative_ then the resulting path is also relative.+localToPath :: MonadIO io => FilePrefix -> File -> io FilePath+localToPath prefix file_ = liftIO $ do+    let File {..} = file_++    let Directory {..} = directory++    prefixPath <- case prefix of+        Home ->+            Directory.getHomeDirectory++        Absolute ->+            return "/"++        Parent ->+            return ".."++        Here ->+            return "."++    let cs = map Text.unpack (file : components)++    let cons component dir = dir </> component++    return (foldr cons prefixPath cs)++-- | Given a `Local` import construct the corresponding unhashed `Chained`+--   import (interpreting relative path as relative to the current directory).+chainedFromLocalHere :: FilePrefix -> File -> ImportMode -> Chained+chainedFromLocalHere prefix file mode = Chained $+     Import (ImportHashed Nothing (Local prefix (canonicalize file))) mode++-- | Adjust the import mode of a chained import+chainedChangeMode :: ImportMode -> Chained -> Chained+chainedChangeMode mode (Chained (Import importHashed _)) =+    Chained (Import importHashed mode)++-- | Chain imports, also typecheck and normalize headers if applicable.+chainImport :: Chained -> Import -> StateT Status IO Chained+chainImport (Chained parent) child@(Import importHashed@(ImportHashed _ (Remote url)) _) = do+    url' <- normalizeHeadersIn url+    let child' = child { importHashed = importHashed { importType = Remote url' } }+    return (Chained (canonicalize (parent <> child')))++chainImport (Chained parent) child =+    return (Chained (canonicalize (parent <> child)))++-- | Load an import, resulting in a fully resolved, type-checked and normalised+--   expression. @loadImport@ handles the \"hot\" cache in @Status@ and defers+--   to @loadImportWithSemanticCache@ for imports that aren't in the @Status@+--   cache already.+loadImport :: Chained -> StateT Status IO ImportSemantics+loadImport import_ = do+    Status {..} <- State.get++    case Dhall.Map.lookup import_ _cache of+        Just importSemantics -> return importSemantics+        Nothing -> do+            importSemantics <- loadImportWithSemanticCache import_+            zoom cache (State.modify (Dhall.Map.insert import_ importSemantics))+            return importSemantics++-- | Load an import from the 'semantic cache'. Defers to+--   @loadImportWithSemisemanticCache@ for imports that aren't frozen (and+--   therefore not cached semantically), as well as those that aren't cached yet.+loadImportWithSemanticCache :: Chained -> StateT Status IO ImportSemantics+loadImportWithSemanticCache+  import_@(Chained (Import (ImportHashed Nothing _) _)) =+    loadImportWithSemisemanticCache import_++loadImportWithSemanticCache+  import_@(Chained (Import _ Location)) =+    loadImportWithSemisemanticCache import_++loadImportWithSemanticCache+  import_@(Chained (Import (ImportHashed (Just semanticHash) _) _)) = do+    Status { .. } <- State.get+    mCached <-+        case _semanticCacheMode of+            UseSemanticCache ->+                zoom cacheWarning (fetchFromSemanticCache semanticHash)+            IgnoreSemanticCache ->+                pure Nothing++    case mCached of+        Just bytesStrict -> do+            let actualHash = Dhall.Crypto.sha256Hash bytesStrict++            if semanticHash == actualHash+                then do+                    let bytesLazy = Data.ByteString.Lazy.fromStrict bytesStrict++                    importSemantics <- case Dhall.Binary.decodeExpression bytesLazy of+                        Left  err -> throwMissingImport (Imported _stack err)+                        Right e   -> return e++                    return (ImportSemantics {..})+                else do+                    printWarning $+                        makeHashMismatchMessage semanticHash actualHash+                        <> "\n"+                        <> "The interpreter will attempt to fix the cached import\n"+                    fetch+++        Nothing -> fetch+    where+        fetch = do+            ImportSemantics{ importSemantics } <- loadImportWithSemisemanticCache import_++            let bytes = encodeExpression (Core.alphaNormalize importSemantics)++            let actualHash = Dhall.Crypto.sha256Hash bytes++            let expectedHash = semanticHash++            if actualHash == expectedHash+                then do+                    zoom cacheWarning (writeToSemanticCache semanticHash bytes)++                else do+                    Status{ _stack } <- State.get++                    throwMissingImport (Imported _stack HashMismatch{..})++            return ImportSemantics{..}++++-- Fetch encoded normal form from "semantic cache"+fetchFromSemanticCache+    :: (MonadState CacheWarning m, MonadCatch m, MonadIO m)+    => Dhall.Crypto.SHA256Digest+    -> m (Maybe Data.ByteString.ByteString)+fetchFromSemanticCache expectedHash = Maybe.runMaybeT $ do+    cacheFile <- getCacheFile "dhall" expectedHash+    True <- liftIO (Directory.doesFileExist cacheFile)+    liftIO (Data.ByteString.readFile cacheFile)++-- | Ensure that the given expression is present in the semantic cache. The+--   given expression should be alpha-beta-normal.+writeExpressionToSemanticCache :: Expr Void Void -> IO ()+writeExpressionToSemanticCache expression =+    -- Defaulting to not displaying the warning is for backwards compatibility+    -- with the old behavior+    State.evalStateT (writeToSemanticCache hash bytes) CacheWarned+  where+    bytes = encodeExpression expression++    hash = Dhall.Crypto.sha256Hash bytes++writeToSemanticCache+    :: (MonadState CacheWarning m, MonadCatch m, MonadIO m)+    => Dhall.Crypto.SHA256Digest+    -> Data.ByteString.ByteString+    -> m ()+writeToSemanticCache hash bytes = do+    _ <- Maybe.runMaybeT $ do+        cacheFile <- getCacheFile "dhall" hash+        liftIO (AtomicWrite.Binary.atomicWriteFile cacheFile bytes)+    return ()++-- Check the "semi-semantic" disk cache, otherwise typecheck and normalise from+-- scratch.+loadImportWithSemisemanticCache+  :: Chained -> StateT Status IO ImportSemantics+loadImportWithSemisemanticCache (Chained (Import (ImportHashed _ importType) Code)) = do+    text <- fetchFresh importType+    Status {..} <- State.get++    path <- case importType of+        Local prefix file -> liftIO $ do+            path <- localToPath prefix file+            absolutePath <- Directory.makeAbsolute path+            return absolutePath+        Remote url -> do+            let urlText = Core.pretty (url { headers = Nothing })+            return (Text.unpack urlText)+        Env env -> return $ Text.unpack env+        Missing -> throwM (MissingImports [])++    let parser = unParser $ do+            Text.Parser.Token.whiteSpace+            r <- Dhall.Parser.expr+            Text.Parser.Combinators.eof+            return r++    parsedImport <- case Text.Megaparsec.parse parser path text of+        Left  errInfo ->+            throwMissingImport (Imported _stack (ParseError errInfo text))+        Right expr    -> return expr++    resolvedExpr <- loadWith parsedImport  -- we load imports recursively here++    -- Check the semi-semantic cache. See+    -- https://github.com/dhall-lang/dhall-haskell/issues/1098 for the reasoning+    -- behind semi-semantic caching.+    let semisemanticHash = computeSemisemanticHash (Core.denote resolvedExpr)++    mCached <- zoom cacheWarning (fetchFromSemisemanticCache semisemanticHash)++    importSemantics <- case mCached of+        Just bytesStrict -> do+            let bytesLazy = Data.ByteString.Lazy.fromStrict bytesStrict++            importSemantics <- case Dhall.Binary.decodeExpression bytesLazy of+                Left err  -> throwMissingImport (Imported _stack err)+                Right sem -> return sem++            return importSemantics++        Nothing -> do+            let substitutedExpr =+                  Dhall.Substitution.substitute resolvedExpr _substitutions++            case Core.shallowDenote parsedImport of+                -- If this import trivially wraps another import, we can skip+                -- the type-checking and normalization step as the transitive+                -- import was already type-checked and normalized+                Embed _ ->+                    return (Core.denote substitutedExpr)++                _ -> do+                    case Dhall.TypeCheck.typeWith _startingContext substitutedExpr of+                        Left  err -> throwMissingImport (Imported _stack err)+                        Right _   -> return ()++                    let betaNormal =+                            Core.normalizeWith _normalizer substitutedExpr++                    let bytes = encodeExpression betaNormal++                    zoom cacheWarning (writeToSemisemanticCache semisemanticHash bytes)++                    return betaNormal++    return (ImportSemantics {..})++-- `as Text` and `as Bytes` imports aren't cached since they are well-typed and+-- normal by construction+loadImportWithSemisemanticCache (Chained (Import (ImportHashed _ importType) RawText)) = do+    text <- fetchFresh importType++    -- importSemantics is alpha-beta-normal by construction!+    let importSemantics = TextLit (Chunks [] text)+    return (ImportSemantics {..})+loadImportWithSemisemanticCache (Chained (Import (ImportHashed _ importType) RawBytes)) = do+    bytes <- fetchBytes importType++    -- importSemantics is alpha-beta-normal by construction!+    let importSemantics = BytesLit bytes+    return (ImportSemantics {..})++-- `as Location` imports aren't cached since they are well-typed and normal by+-- construction+loadImportWithSemisemanticCache (Chained (Import (ImportHashed _ importType) Location)) = do+    let locationType = Union $ Dhall.Map.fromList+            [ ("Environment", Just Text)+            , ("Remote", Just Text)+            , ("Local", Just Text)+            , ("Missing", Nothing)+            ]++    -- importSemantics is alpha-beta-normal by construction!+    let importSemantics = case importType of+            Missing -> Field locationType $ Core.makeFieldSelection  "Missing"+            local@(Local _ _) ->+                App (Field locationType $ Core.makeFieldSelection "Local")+                  (TextLit (Chunks [] (Core.pretty local)))+            remote_@(Remote _) ->+                App (Field locationType $ Core.makeFieldSelection "Remote")+                  (TextLit (Chunks [] (Core.pretty remote_)))+            Env env ->+                App (Field locationType $ Core.makeFieldSelection "Environment")+                  (TextLit (Chunks [] (Core.pretty env)))++    return (ImportSemantics {..})++-- The semi-semantic hash of an expression is computed from the fully resolved+-- AST (without normalising or type-checking it first). See+-- https://github.com/dhall-lang/dhall-haskell/issues/1098 for further+-- discussion.+computeSemisemanticHash :: Expr Void Void -> Dhall.Crypto.SHA256Digest+computeSemisemanticHash resolvedExpr = hashExpression resolvedExpr++-- Fetch encoded normal form from "semi-semantic cache"+fetchFromSemisemanticCache+    :: (MonadState CacheWarning m, MonadCatch m, MonadIO m)+    => Dhall.Crypto.SHA256Digest+    -> m (Maybe Data.ByteString.ByteString)+fetchFromSemisemanticCache semisemanticHash = Maybe.runMaybeT $ do+    cacheFile <- getCacheFile "dhall-haskell" semisemanticHash+    True <- liftIO (Directory.doesFileExist cacheFile)+    liftIO (Data.ByteString.readFile cacheFile)++writeToSemisemanticCache+    :: (MonadState CacheWarning m, MonadCatch m, MonadIO m)+    => Dhall.Crypto.SHA256Digest+    -> Data.ByteString.ByteString+    -> m ()+writeToSemisemanticCache semisemanticHash bytes = do+    _ <- Maybe.runMaybeT $ do+        cacheFile <- getCacheFile "dhall-haskell" semisemanticHash+        liftIO (AtomicWrite.Binary.atomicWriteFile cacheFile bytes)+    return ()++-- | Fetch source code directly from disk/network+fetchFresh :: ImportType -> StateT Status IO Text+fetchFresh (Local prefix file) = do+    Status { _stack } <- State.get+    path <- liftIO $ localToPath prefix file+    exists <- liftIO $ Directory.doesFileExist path+    if exists+        then liftIO $ Data.Text.IO.readFile path+        else throwMissingImport (Imported _stack (MissingFile path))++fetchFresh (Remote url) = do+    Status { _remote } <- State.get+    _remote url++fetchFresh (Env env) = do+    Status { _stack } <- State.get+    x <- liftIO $ System.Environment.lookupEnv (Text.unpack env)+    case x of+        Just string ->+            return (Text.pack string)+        Nothing ->+                throwMissingImport (Imported _stack (MissingEnvironmentVariable env))++fetchFresh Missing = throwM (MissingImports [])++-- | Like `fetchFresh`, except for `Dhall.Syntax.Expr.Bytes`+fetchBytes :: ImportType -> StateT Status IO ByteString+fetchBytes (Local prefix file) = do+    Status { _stack } <- State.get+    path <- liftIO $ localToPath prefix file+    exists <- liftIO $ Directory.doesFileExist path+    if exists+        then liftIO $ Data.ByteString.readFile path+        else throwMissingImport (Imported _stack (MissingFile path))++fetchBytes (Remote url) = do+    Status { _remoteBytes } <- State.get+    _remoteBytes url++fetchBytes (Env env) = do+    Status { _stack } <- State.get+    x <- liftIO $ System.Environment.lookupEnv (Text.unpack env)+    case x of+        Just string ->+            return (Encoding.encodeUtf8 (Text.pack string))+        Nothing ->+            throwMissingImport (Imported _stack (MissingEnvironmentVariable env))+fetchBytes Missing = throwM (MissingImports [])++-- | Fetch the text contents of a URL+fetchRemote :: URL -> StateT Status IO Data.Text.Text+#ifndef WITH_HTTP+fetchRemote (url@URL { headers = maybeHeadersExpression }) = do+    let maybeHeaders = fmap toHeaders maybeHeadersExpression+    let urlString = Text.unpack (Core.pretty url)+    Status { _stack } <- State.get+    throwMissingImport (Imported _stack (CannotImportHTTPURL urlString maybeHeaders))+#else+fetchRemote url = do+    zoom remote (State.put fetchFromHTTP)+    fetchFromHTTP url+  where+    fetchFromHTTP :: URL -> StateT Status IO Data.Text.Text+    fetchFromHTTP (url'@URL { headers = maybeHeadersExpression }) = do+        let maybeHeaders = fmap toHeaders maybeHeadersExpression+        fetchFromHttpUrl url' maybeHeaders+#endif++-- | Fetch the text contents of a URL+fetchRemoteBytes :: URL -> StateT Status IO Data.ByteString.ByteString+#ifndef WITH_HTTP+fetchRemoteBytes (url@URL { headers = maybeHeadersExpression }) = do+    let maybeHeaders = fmap toHeaders maybeHeadersExpression+    let urlString = Text.unpack (Core.pretty url)+    Status { _stack } <- State.get+    throwMissingImport (Imported _stack (CannotImportHTTPURL urlString maybeHeaders))+#else+fetchRemoteBytes url = do+    zoom remoteBytes (State.put fetchFromHTTP)+    fetchFromHTTP url+  where+    fetchFromHTTP :: URL -> StateT Status IO Data.ByteString.ByteString+    fetchFromHTTP (url'@URL { headers = maybeHeadersExpression }) = do+        let maybeHeaders = fmap toHeaders maybeHeadersExpression+        fetchFromHttpUrlBytes url' maybeHeaders+#endif++getCacheFile+    :: (MonadCatch m, Alternative m, MonadState CacheWarning m, MonadIO m)+    => FilePath -> Dhall.Crypto.SHA256Digest -> m FilePath+getCacheFile cacheName hash = do+    cacheDirectory <- getOrCreateCacheDirectory cacheName++    let cacheFile = cacheDirectory </> ("1220" <> show hash)++    return cacheFile++getOrCreateCacheDirectory+    :: (MonadCatch m, Alternative m, MonadState CacheWarning m, MonadIO m)+    => FilePath -> m FilePath+getOrCreateCacheDirectory cacheName = do+    let warn message = do+            cacheWarningStatus <- State.get++            case cacheWarningStatus of+                CacheWarned    -> printWarning message+                CacheNotWarned -> return ()++            State.put CacheWarned++            empty++    let handler action dir (ioex :: IOException) = do+            let ioExMsg =+                     "When trying to " <> action <> ":\n"+                  <> "\n"+                  <> "↳ " <> dir <> "\n"+                  <> "\n"+                  <> "... the following exception was thrown:\n"+                  <> "\n"+                  <> "↳ " <> show ioex <> "\n"++            warn ioExMsg++    let setPermissions dir = do+            let private = transform Directory.emptyPermissions+                    where+                        transform =+                            Directory.setOwnerReadable   True+                          . Directory.setOwnerWritable   True+                          . Directory.setOwnerSearchable True++            catch+                (liftIO (Directory.setPermissions dir private))+                (handler "correct the permissions for" dir)++    let assertPermissions dir = do+            let accessible path =+                    Directory.readable   path+                 && Directory.writable   path+                 && Directory.searchable path++            permissions <-+                catch (liftIO (Directory.getPermissions dir))+                      (handler "get permissions of" dir)++            if accessible permissions+                then+                    return ()+                else do+                    let render f = if f permissions then "✓" else "✗"+                    let message =+                             "The directory:\n"+                          <> "\n"+                          <> "↳ " <> dir <> "\n"+                          <> "\n"+                          <> "... does not give you permission to read, write, or search files.\n\n"+                          <> "\n"+                          <> "The directory's current permissions are:\n"+                          <> "\n"+                          <> "• " <> render Directory.readable <> " readable\n"+                          <> "• " <> render Directory.writable <> " writable\n"+                          <> "• " <> render Directory.searchable <> " searchable\n"++                    warn message++    let existsDirectory dir =+            catch (liftIO (Directory.doesDirectoryExist dir))+                  (handler "check the existence of" dir)++    let existsFile path =+            catch (liftIO (Directory.doesFileExist path))+                  (handler "check the existence of" path)++    let createDirectory dir =+            catch (liftIO (Directory.createDirectory dir))+                  (handler "create" dir)++    let assertDirectory dir = do+            existsDir <- existsDirectory dir++            if existsDir+                then+                    assertPermissions dir++                else do+                    existsFile' <- existsFile dir++                    if existsFile'+                        then do+                            let message =+                                     "The given path:\n"+                                  <> "\n"+                                  <> "↳ " <> dir <> "\n"+                                  <> "\n"+                                  <> "... already exists but is not a directory.\n"++                            warn message++                        else do+                            assertDirectory (FilePath.takeDirectory dir)++                            createDirectory dir++                            setPermissions dir++    cacheBaseDirectory <- getCacheBaseDirectory++    let directory = cacheBaseDirectory </> cacheName++    let message =+             "Could not get or create the default cache directory:\n"+          <> "\n"+          <> "↳ " <> directory <> "\n"+          <> "\n"+          <> "You can enable caching by creating it if needed and setting read,\n"+          <> "write and search permissions on it or providing another cache base\n"+          <> "directory by setting the $XDG_CACHE_HOME environment variable.\n"+          <> "\n"++    assertDirectory directory <|> warn message++    return directory++getCacheBaseDirectory+    :: (MonadState CacheWarning m, Alternative m, MonadIO m) => m FilePath+getCacheBaseDirectory = alternative₀ <|> alternative₁ <|> alternative₂+  where+    alternative₀ = do+        maybeXDGCacheHome <-+          liftIO (System.Environment.lookupEnv "XDG_CACHE_HOME")++        case maybeXDGCacheHome of+            Just xdgCacheHome -> return xdgCacheHome+            Nothing           -> empty++    alternative₁+        | isWindows = do+            maybeLocalAppDirectory <-+              liftIO (System.Environment.lookupEnv "LOCALAPPDATA")++            case maybeLocalAppDirectory of+                Just localAppDirectory -> return localAppDirectory+                Nothing                -> empty++        | otherwise = do+            maybeHomeDirectory <-+              liftIO (System.Environment.lookupEnv "HOME")++            case maybeHomeDirectory of+                Just homeDirectory -> return (homeDirectory </> ".cache")+                Nothing            -> empty++        where isWindows = System.Info.os == "mingw32"++    alternative₂ = do+        cacheWarningStatus <- State.get++        let message =+                "\n"+             <> "\ESC[1;33mWarning\ESC[0m: "+             <> "Could not locate a cache base directory from the environment.\n"+             <> "\n"+             <> "You can provide a cache base directory by pointing the $XDG_CACHE_HOME\n"+             <> "environment variable to a directory with read and write permissions.\n"++        case cacheWarningStatus of+            CacheNotWarned ->+                liftIO (System.IO.hPutStrLn System.IO.stderr message)+            CacheWarned ->+                return ()++        State.put CacheWarned++        empty++-- If the URL contains headers typecheck them and replace them with their normal+-- forms.+normalizeHeadersIn :: URL -> StateT Status IO URL+normalizeHeadersIn url@URL { headers = Just headersExpression } = do+    Status { _stack } <- State.get+    loadedExpr <- loadWith headersExpression+    let handler (e :: SomeException) = throwMissingImport (Imported _stack e)+    normalized <- liftIO $ handle handler (normalizeHeaders loadedExpr)+    return url { headers = Just (fmap absurd normalized) }++normalizeHeadersIn url = return url++-- | Empty origin headers used for remote contexts+--   (and fallback when nothing is set in env or config file)+emptyOriginHeaders :: Expr Src Import+emptyOriginHeaders = ListLit (Just (fmap absurd originHeadersTypeExpr)) mempty++-- | A fake Src to annotate headers expressions with.+--   We need to wrap headers expressions in a Note for nice error reporting,+--   and because ImportAlt handling only catches SourcedExceptions+headersSrc :: Src+headersSrc = Src {+        srcStart = SourcePos {+            sourceName = fakeSrcName,+            sourceLine = mkPos 1,+            sourceColumn = mkPos 1+        },+        srcEnd = SourcePos {+            sourceName = fakeSrcName,+            sourceLine = mkPos 1,+            sourceColumn = mkPos (Text.length fakeSrcText)+        },+        srcText = fakeSrcText+    }+  where+    fakeSrcText = "«Origin Header Configuration»"+    fakeSrcName = "[builtin]"++-- | Load headers only from the environment (used in tests)+envOriginHeaders :: Expr Src Import+envOriginHeaders = Note headersSrc (Embed (Import (ImportHashed Nothing (Env "DHALL_HEADERS")) Code))++-- | Load headers in env, falling back to config file+defaultOriginHeaders :: IO (Expr Src Import)+#ifndef WITH_HTTP+defaultOriginHeaders = return emptyOriginHeaders+#else+defaultOriginHeaders = do+    fromFile <- originHeadersFileExpr+    return (Note headersSrc (ImportAlt envOriginHeaders (Note headersSrc fromFile)))+#endif++-- | Given a headers expression, return an origin headers loader+originHeadersLoader :: IO (Expr Src Import) -> StateT Status IO OriginHeaders+originHeadersLoader headersExpr = do++    -- Load the headers using the parent stack, which should always be a local+    -- import (we only load headers for the first remote import)++    status <- State.get++    let parentStack = fromMaybe abortEmptyStack (nonEmpty (NonEmpty.tail (_stack status)))++    let headerLoadStatus = status { _stack = parentStack }++    (headers, _) <- liftIO (State.runStateT doLoad headerLoadStatus)++    -- return cached headers next time+    _ <- State.modify (\state -> state { _loadOriginHeaders = return headers })++    return headers+  where+    abortEmptyStack = Core.internalError "Origin headers loaded with an empty stack"++    doLoad = do+        partialExpr <- liftIO headersExpr+        loaded <- loadWith (Note headersSrc (ImportAlt partialExpr emptyOriginHeaders))+        liftIO (toOriginHeaders loaded)++-- | Default starting `Status`, importing relative to the given directory.+emptyStatus :: FilePath -> Status+emptyStatus = makeEmptyStatus defaultNewManager defaultOriginHeaders++-- | See 'emptyStatus'+emptyStatusWithManager+    :: IO Manager+    -> FilePath+    -> Status+emptyStatusWithManager newManager = makeEmptyStatus newManager defaultOriginHeaders++-- | See 'emptyStatus'.+makeEmptyStatus+    :: IO Manager+    -> IO (Expr Src Import)+    -> FilePath+    -> Status+makeEmptyStatus newManager headersExpr rootDirectory =+    emptyStatusWith newManager (originHeadersLoader headersExpr) fetchRemote fetchRemoteBytes rootImport+  where+    prefix = if FilePath.isRelative rootDirectory+      then Here+      else Absolute++    pathComponents =+        fmap Text.pack (reverse (FilePath.splitDirectories rootDirectory))++    directoryAsFile = File (Directory pathComponents) "."++    rootImport = Import+      { importHashed = ImportHashed+        { hash = Nothing+        , importType = Local prefix directoryAsFile+        }+      , importMode = Code+      }++{-| Default `Status` appropriate for a server interpreting Dhall code++    Using this `Status` ensures that interpreted Dhall code cannot access+    server-local resources (like files or environment variables)+-}+remoteStatus+    :: URL+    -- ^ Public address of the server+    -> Status+remoteStatus = remoteStatusWithManager defaultNewManager++-- | See `remoteStatus`+remoteStatusWithManager :: IO Manager -> URL -> Status+remoteStatusWithManager newManager url =+    emptyStatusWith newManager (originHeadersLoader (pure emptyOriginHeaders)) fetchRemote fetchRemoteBytes rootImport+  where+    rootImport = Import+      { importHashed = ImportHashed+        { hash = Nothing+        , importType = Remote url+        }+      , importMode = Code+      }++{-| Generalized version of `load`++    You can configure the desired behavior through the initial `Status` that you+    supply+-}+loadWith :: Expr Src Import -> StateT Status IO (Expr Src Void)+loadWith expr₀ = case expr₀ of+  Embed import₀ -> do+    Status {..} <- State.get++    let parent = NonEmpty.head _stack++    child <- chainImport parent import₀++    let local (Chained (Import (ImportHashed _ (Remote  {})) _)) = False+        local (Chained (Import (ImportHashed _ (Local   {})) _)) = True+        local (Chained (Import (ImportHashed _ (Env     {})) _)) = True+        local (Chained (Import (ImportHashed _ (Missing {})) _)) = False++    let referentiallySane = not (local child) || local parent++    if importMode import₀ == Location || referentiallySane+        then return ()+        else throwMissingImport (Imported _stack (ReferentiallyOpaque import₀))++    let _stack' = NonEmpty.cons child _stack++    if child `elem` _stack+        then throwMissingImport (Imported _stack (Cycle import₀))+        else return ()++    zoom graph . State.modify $+        -- Add the edge `parent -> child` to the import graph+        \edges -> Depends parent child : edges++    let stackWithChild = NonEmpty.cons child _stack++    zoom stack (State.put stackWithChild)+    ImportSemantics {..} <- loadImport child+    zoom stack (State.put _stack)++    return (Core.renote importSemantics)++  ImportAlt a b -> loadWith a `catch` handler₀+    where+      is :: forall e . Exception e => SomeException -> Bool+      is exception = Maybe.isJust (Exception.fromException @e exception)++      isNotResolutionError exception =+              is @(Imported (TypeError Src Void)) exception+          ||  is @(Imported  Cycle              ) exception+          ||  is @(Imported  HashMismatch       ) exception+          ||  is @(Imported  ParseError         ) exception++      handler₀ exception₀@(SourcedException (Src begin _ text₀) (MissingImports es₀))+          | any isNotResolutionError es₀ =+              throwM exception₀+          | otherwise = do+              loadWith b `catch` handler₁+        where+          handler₁ exception₁@(SourcedException (Src _ end text₁) (MissingImports es₁))+              | any isNotResolutionError es₁ =+                  throwM exception₁+              | otherwise =+                  -- Fix the source span for the error message to encompass both+                  -- alternatives, since both are equally to blame for the+                  -- failure if neither succeeds.+                  throwM (SourcedException (Src begin end text₂) (MissingImports (es₀ ++ es₁)))+            where+              text₂ = text₀ <> " ? " <> text₁++  Note a b             -> do+      let handler e = throwM (SourcedException a (e :: MissingImports))++      (Note <$> pure a <*> loadWith b) `catch` handler+  Let a b              -> Let <$> bindingExprs loadWith a <*> loadWith b+  Record m             -> Record <$> traverse (recordFieldExprs loadWith) m+  RecordLit m          -> RecordLit <$> traverse (recordFieldExprs loadWith) m+  Lam cs a b           -> Lam cs <$> functionBindingExprs loadWith a <*> loadWith b+  Field a b            -> Field <$> loadWith a <*> pure b+  expression           -> Syntax.unsafeSubExpressions loadWith expression++-- | Resolve all imports within an expression+load :: Expr Src Import -> IO (Expr Src Void)+load = loadWithManager defaultNewManager++-- | See 'load'.+loadWithManager :: IO Manager -> Expr Src Import -> IO (Expr Src Void)+loadWithManager newManager =+    loadWithStatus+        (makeEmptyStatus newManager defaultOriginHeaders ".")+        UseSemanticCache++-- | Resolve all imports within an expression, importing relative to the given+-- directory.+loadRelativeTo :: FilePath -> SemanticCacheMode -> Expr Src Import -> IO (Expr Src Void)+loadRelativeTo parentDirectory = loadWithStatus+    (makeEmptyStatus defaultNewManager defaultOriginHeaders parentDirectory)++-- | See 'loadRelativeTo'.+loadWithStatus+    :: Status+    -> SemanticCacheMode+    -> Expr Src Import+    -> IO (Expr Src Void)+loadWithStatus status semanticCacheMode expression =+    State.evalStateT+        (loadWith expression)+        status { _semanticCacheMode = semanticCacheMode }++encodeExpression :: Expr Void Void -> Data.ByteString.ByteString+encodeExpression expression = bytesStrict+  where+    intermediateExpression :: Expr Void Import+    intermediateExpression = fmap absurd expression++    encoding = Codec.Serialise.encode intermediateExpression++    bytesStrict = Write.toStrictByteString encoding++-- | Hash a fully resolved expression+hashExpression :: Expr Void Void -> Dhall.Crypto.SHA256Digest+hashExpression = Dhall.Crypto.sha256Hash . encodeExpression++{-| Convenience utility to hash a fully resolved expression and return the+    base-16 encoded hash with the @sha256:@ prefix++    In other words, the output of this function can be pasted into Dhall+    source code to add an integrity check to an import+-}+hashExpressionToCode :: Expr Void Void -> Text+hashExpressionToCode expr =+    "sha256:" <> Text.pack (show (hashExpression expr))++-- | A call to `assertNoImports` failed because there was at least one import+data ImportResolutionDisabled = ImportResolutionDisabled deriving (Exception)++instance Show ImportResolutionDisabled where+    show _ = "\nImport resolution is disabled"++-- | Assert than an expression is import-free+assertNoImports :: MonadIO io => Expr Src Import -> io (Expr Src Void)+assertNoImports expression =+    Core.throws (traverse (\_ -> Left ImportResolutionDisabled) expression)+{-# INLINABLE assertNoImports #-}++{-| This function is used by the @--transitive@ option of the+    @dhall {freeze,format,lint}@ subcommands to determine which dependencies+    to descend into++#ifndef mingw32_HOST_OS+    >>> dependencyToFile (emptyStatus ".") Import{ importHashed = ImportHashed{ hash = Nothing, importType = Local Here (File (Directory []) "foo") }, importMode = Code }+    Just "./foo"++    >>> dependencyToFile (emptyStatus "./foo") Import{ importHashed = ImportHashed{ hash = Nothing, importType = Local Here (File (Directory []) "bar") }, importMode = Code }+    Just "./foo/bar"+++    >>> dependencyToFile (emptyStatus "./foo") Import{ importHashed = ImportHashed{ hash = Nothing, importType = Remote (URL HTTPS "example.com" (File (Directory []) "") Nothing Nothing) }, importMode = Code }+    Nothing++    >>> dependencyToFile (emptyStatus ".") Import{ importHashed = ImportHashed{ hash = Nothing, importType = Env "foo" }, importMode = Code }+    Nothing+#endif+-}+dependencyToFile :: Status -> Import -> IO (Maybe FilePath)+dependencyToFile status import_ = flip State.evalStateT status $ do+    parent :| _ <- zoom stack State.get++    child <- fmap chainedImport (hoist liftIO (chainImport parent import_))++    let ignore = return Nothing++    -- We only need to transitively modify code imports since other import+    -- types are not interpreted and therefore don't need to be modified+    case importMode child of+        RawText ->+            ignore++        RawBytes ->+            ignore++        Location ->+            ignore++        Code ->+            case importType (importHashed child) of+                Local filePrefix file -> do+                    let descend = liftIO $ do+                            path <- localToPath filePrefix file++                            return (Just path)++                    -- Only follow relative imports when modifying dependencies.+                    -- Carefully note that we check the file prefix of the+                    -- original import (before chaining), since the chained+                    -- import will inherit the file prefix of the parent import.+                    case importType (importHashed import_) of+                        Local Here   _ -> descend+                        Local Parent _ -> descend+                        _              -> ignore++                -- Don't transitively modify any other type of import+                Remote{} ->+                    ignore++                Missing ->+                    ignore++                Env{} ->+                    ignore
− src/Dhall/Import/HTTP.hs
@@ -1,290 +0,0 @@-{-# LANGUAGE CPP               #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecordWildCards   #-}--module Dhall.Import.HTTP where--import Control.Exception (Exception)-import Control.Monad (join)-import Control.Monad.IO.Class (MonadIO(..))-import Control.Monad.Trans.State.Strict (StateT)-import Data.ByteString (ByteString)-import Data.CaseInsensitive (CI)-import Data.Dynamic (fromDynamic, toDyn)-import Data.Semigroup ((<>))-import Data.Text (Text)-import Lens.Family.State.Strict (zoom)--import Dhall.Core-    ( Directory(..)-    , File(..)-    , Import(..)-    , ImportHashed(..)-    , ImportType(..)-    , Scheme(..)-    , URL(..)-    )--import qualified Control.Monad.Trans.State.Strict as State-import qualified Data.Text                        as Text-import qualified Data.Text.Encoding-import qualified Dhall.Util-import qualified Network.URI.Encode               as URI.Encode--import Dhall.Import.Types--import qualified Control.Exception-#ifdef __GHCJS__-import qualified JavaScript.XHR-#else-import qualified Data.List.NonEmpty               as NonEmpty-import qualified Data.Text.Lazy-import qualified Data.Text.Lazy.Encoding-#endif--#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.Types.Status--mkPrettyHttpException :: HttpException -> PrettyHttpException-mkPrettyHttpException ex =-    PrettyHttpException (renderPrettyHttpException ex) (toDyn ex)--renderPrettyHttpException :: HttpException -> String-#if MIN_VERSION_http_client(0,5,0)-renderPrettyHttpException (InvalidUrlException _ r) =-  "\n"-  <>  "\ESC[1;31mError\ESC[0m: Invalid URL\n"-  <>  "\n"-  <>  "↳ " <> show r-renderPrettyHttpException (HttpExceptionRequest _ e) =-  case e of-    ConnectionFailure _ ->-      "\n"-      <>  "\ESC[1;31mError\ESC[0m: Remote host not found\n"-    InvalidDestinationHost host ->-      "\n"-      <>  "\ESC[1;31mError\ESC[0m: Invalid remote host name\n"-      <>  "\n"-      <>  "↳ " <> show host-    ResponseTimeout ->-      "\n"-      <>  "\ESC[1;31mError\ESC[0m: The remote host took too long to respond"-    StatusCodeException response _-        | statusCode == 404 ->-            "\n"-            <>  "\ESC[1;31mError\ESC[0m: Remote file not found"-        | otherwise ->-            "\n"-            <>  "\ESC[1;31mError\ESC[0m: Unexpected HTTP status code:\n"-            <>  "\n"-            <>  "↳ " <> show statusCode-      where-        statusCode =-            Network.HTTP.Types.Status.statusCode-                (HTTP.responseStatus response)-    e' -> "\n" <> show e'-#else-renderPrettyHttpException e = case e of-    FailedConnectionException2 _ _ _ e' ->-            "\n"-        <>  "\ESC[1;31mError\ESC[0m: Wrong host\n"-        <>  "\n"-        <>  "↳ " <> show e'-    InvalidDestinationHost host ->-            "\n"-        <>  "\ESC[1;31mError\ESC[0m: Invalid host name\n"-        <>  "\n"-        <>  "↳ " <> show host-    ResponseTimeout ->-            "\ESC[1;31mError\ESC[0m: The host took too long to respond\n"-    e' ->   "\n"-        <> show e'-#endif--needManager :: StateT (Status m) IO Manager-needManager = do-    x <- zoom manager State.get-    case join (fmap fromDynamic x) of-        Just m  -> return m-        Nothing -> do-            let settings = HTTP.tlsManagerSettings--#ifdef MIN_VERSION_http_client-#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-#endif-            m <- liftIO (HTTP.newManager settings)-            zoom manager (State.put (Just (toDyn m)))-            return m--data NotCORSCompliant = NotCORSCompliant-    { expectedOrigins :: [ByteString]-    , actualOrigin    :: ByteString-    }--instance Exception NotCORSCompliant--instance Show NotCORSCompliant where-    show (NotCORSCompliant {..}) =-            Dhall.Util._ERROR <> ": Not CORS compliant\n"-        <>  "\n"-        <>  "Dhall supports transitive imports, meaning that an imported expression can\n"-        <>  "import other expressions.  However, a remote import (the \"parent\" import)\n"-        <>  "cannot import another remote import (the \"child\" import) unless the child\n"-        <>  "import grants permission to do using CORS.  The child import must respond with\n"-        <>  "an `Access-Control-Allow-Origin` response header that matches the parent\n"-        <>  "import, otherwise Dhall rejects the import.\n"-        <>  "\n" <> prologue-      where-        prologue =-            case expectedOrigins of-                [ expectedOrigin ] ->-                        "The following parent import:\n"-                    <>  "\n"-                    <>  "↳ " <> show actualOrigin <> "\n"-                    <>  "\n"-                    <>  "... did not match the expected origin:\n"-                    <>  "\n"-                    <>  "↳ " <> show expectedOrigin <> "\n"-                    <>  "\n"-                    <>  "... so import resolution failed.\n"-                [] ->-                        "The child response did not include any `Access-Control-Allow-Origin` header,\n"-                    <>  "so import resolution failed.\n"-                _:_:_ ->-                        "The child response included more than one `Access-Control-Allow-Origin` header,\n"-                    <>  "when only one such header should have been present, so import resolution\n"-                    <>  "failed.\n"-                    <>  "\n"-                    <>  "This may indicate that the server for the child import is misconfigured.\n"--corsCompliant-    :: MonadIO io-    => ImportType -> URL -> [(CI ByteString, ByteString)] -> io ()-corsCompliant (Remote parentURL) childURL responseHeaders = liftIO $ do-    let toOrigin (URL {..}) =-            Data.Text.Encoding.encodeUtf8 (prefix <> "://" <> authority)-          where-            prefix =-                case scheme of-                    HTTP  -> "http"-                    HTTPS -> "https"--    let actualOrigin = toOrigin parentURL--    let childOrigin = toOrigin childURL--    let predicate (header, _) = header == "Access-Control-Allow-Origin"--    let originHeaders = filter predicate responseHeaders--    let expectedOrigins = map snd originHeaders--    case expectedOrigins of-        [expectedOrigin]-            | expectedOrigin == "*" ->-                return ()-            | expectedOrigin == actualOrigin ->-                return ()-        _   | actualOrigin == childOrigin ->-                return ()-            | otherwise ->-                Control.Exception.throwIO (NotCORSCompliant {..})-corsCompliant _ _ _ = return ()--renderComponent :: Text -> Text-renderComponent component = "/" <> URI.Encode.encodeText component--renderQuery :: Text -> Text-renderQuery query = "?" <> query--renderURL :: URL -> Text-renderURL url =-        schemeText-    <>  authority-    <>  pathText-    <>  queryText-  where-    URL {..} = url--    File {..} = path--    Directory {..} = directory--    schemeText = case scheme of-        HTTP  -> "http://"-        HTTPS -> "https://"--    pathText =-            foldMap renderComponent (reverse components)-        <>  renderComponent file--    queryText = foldMap renderQuery query--fetchFromHttpUrl-    :: URL-    -> Maybe [(CI ByteString, ByteString)]-    -> StateT (Status m) IO (String, Text.Text)-#ifdef __GHCJS__-fetchFromHttpUrl childURL Nothing = do-    let childURLText = renderURL childURL--    let childURLString = Text.unpack childURLText--    -- No need to add a CORS compliance check when using GHCJS.  The browser-    -- will already check the CORS compliance of the following XHR-    (statusCode, body) <- liftIO (JavaScript.XHR.get childURLText)--    case statusCode of-        200 -> return ()-        _   -> fail (childURLString <> " returned a non-200 status code: " <> show statusCode)--    return (childURLString, body)-fetchFromHttpUrl _ _ = do-    fail "Dhall does not yet support custom headers when built using GHCJS"-#else-fetchFromHttpUrl childURL mheaders = do-    let childURLString = Text.unpack (renderURL childURL)--    m <- needManager--    request <- liftIO (HTTP.parseUrlThrow childURLString)--    let requestWithHeaders =-            case mheaders of-              Nothing      -> request-              Just headers -> request { HTTP.requestHeaders = headers }--    let io = HTTP.httpLbs requestWithHeaders m--    let handler e = do-            let _ = e :: HttpException-            Control.Exception.throwIO (mkPrettyHttpException e)--    response <- liftIO (Control.Exception.handle handler io)--    Status {..} <- State.get--    let parentImport = NonEmpty.head _stack--    let parentImportType = importType (importHashed parentImport)--    corsCompliant parentImportType childURL (HTTP.responseHeaders response)--    let bytes = HTTP.responseBody response--    case Data.Text.Lazy.Encoding.decodeUtf8' bytes of-        Left  err  -> liftIO (Control.Exception.throwIO err)-        Right text -> return (childURLString, Data.Text.Lazy.toStrict text)-#endif
+ 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
@@ -1,172 +1,209 @@+{-# LANGUAGE CPP               #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards   #-}+ {-# OPTIONS_GHC -Wall #-}  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 Data.Map (Map)-import Data.Semigroup ((<>))-import Dhall.Binary (StandardVersion(..))-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(..)-  , pretty-  )-import Dhall.Parser (Src)-import Dhall.TypeCheck (X)-import Lens.Family (LensLike')-import System.FilePath (isRelative, splitDirectories)-import Text.Dot (Dot, NodeId, userNode, userNodeId)+    ( Expr+    , Import (..)+    , ReifiedNormalizer (..)+    , URL+    )+import Dhall.Map                        (Map)+import Dhall.Parser                     (Src)+import Lens.Micro                       (Lens', lens)+import Prettyprinter                    (Pretty (..)) -import qualified Dhall.Binary-import qualified Dhall.Context-import qualified Data.Map      as Map+#ifdef WITH_HTTP+import qualified Dhall.Import.Manager+#endif+ import qualified Data.Text+import qualified Dhall.Context+import qualified Dhall.Map          as Map+import qualified Dhall.Substitution -data Resolved = Resolved-    { resolvedExpression :: Expr Src Import-    -- ^ Expression with its immediate imports resolved-    , newImport          :: Import-    -- ^ New import to use in place of the original import for chaining-    --   downstream imports+-- | A fully \"chained\" import, i.e. if it contains a relative path that path+--   is relative to the current directory. If it is a remote import with headers+--   those are well-typed (either of type `List { header : Text, value Text}` or+--   `List { mapKey : Text, mapValue Text})` and in normal form. These+--   invariants are preserved by the API exposed by @Dhall.Import@.+newtype Chained = Chained+    { chainedImport :: Import+      -- ^ The underlying import     }+  deriving (Eq, Ord) +instance Pretty Chained where+    pretty (Chained import_) = pretty import_++-- | An import that has been fully interpeted+newtype ImportSemantics = ImportSemantics+    { importSemantics :: Expr Void Void+    -- ^ The fully resolved import, typechecked and beta-normal.+    }++-- | `parent` imports (i.e. depends on) `child`+data Depends = Depends { parent :: Chained, child :: Chained }++{-| This enables or disables the semantic cache for imports protected by+    integrity checks+-}+data SemanticCacheMode = IgnoreSemanticCache | UseSemanticCache deriving (Eq)++-- | Shared state for HTTP requests+type Manager =+#ifdef WITH_HTTP+    Dhall.Import.Manager.Manager+#else+    ()+#endif++-- | The default HTTP 'Manager'+defaultNewManager :: IO Manager+defaultNewManager =+#ifdef WITH_HTTP+  Dhall.Import.Manager.defaultNewManager+#else+  pure ()+#endif++-- | HTTP headers+type HTTPHeader = (CI ByteString, ByteString)++-- | A map of site origin -> HTTP headers+type OriginHeaders = HashMap Data.Text.Text [HTTPHeader]++{-| Used internally to track whether or not we've already warned the user about+    caching issues+-}+data CacheWarning = CacheNotWarned | CacheWarned+ -- | State threaded throughout the import process-data Status m = Status-    { _stack :: NonEmpty Import+data Status = Status+    { _stack :: NonEmpty Chained     -- ^ Stack of `Import`s that we've imported along the way to get to the     -- current point -    , _dot :: Dot NodeId-    -- ^ Graph of all the imports visited so far--    , _nextNodeId :: Int-    -- ^ Next node id to be used for the dot graph generation+    , _graph :: [Depends]+    -- ^ Graph of all the imports visited so far, represented by a list of+    --   import dependencies. -    , _cache :: Map Import (NodeId, Expr Src X)+    , _cache :: Map Chained ImportSemantics     -- ^ Cache of imported expressions with their node id in order to avoid     --   importing the same expression twice with different values -    , _manager :: Maybe Dynamic-    -- ^ Cache for the HTTP `Manager` so that we only acquire it once+    , _newManager :: IO Manager+    , _manager :: Maybe Manager+    -- ^ Used to cache the `Dhall.Import.Manager.Manager` when making multiple+    -- requests -    , _standardVersion :: StandardVersion+    , _loadOriginHeaders :: StateT Status IO OriginHeaders+    -- ^ Load the origin headers from environment or configuration file.+    --   After loading once, further evaluations return the cached version. -    , _normalizer :: Maybe (ReifiedNormalizer X)+    , _remote :: URL -> StateT Status IO Data.Text.Text+    -- ^ The remote resolver, fetches the content at the given URL. -    , _startingContext :: Context (Expr Src X)+    , _remoteBytes :: URL -> StateT Status IO Data.ByteString.ByteString+    -- ^ Like `_remote`, except for `Dhall.Syntax.Expr.Bytes` -    , _resolver :: Import -> StateT (Status m) m Resolved+    , _substitutions :: Dhall.Substitution.Substitutions Src Void -    , _cacher :: Import -> Expr Src X -> StateT (Status m) m ()+    , _normalizer :: Maybe (ReifiedNormalizer Void)++    , _startingContext :: Context (Expr Src Void)++    , _semanticCacheMode :: SemanticCacheMode++    , _cacheWarning :: CacheWarning+    -- ^ Records whether or not we already warned the user about issues with+    --   cache directory     } --- | Default starting `Status` that is polymorphic in the base `Monad`+-- | Initial `Status`, parameterised over the HTTP 'Manager',+--   the origin headers and the remote resolver,+--   importing relative to the given root import. emptyStatusWith-    :: (Import -> StateT (Status m) m Resolved)-    -> (Import -> Expr Src X -> StateT (Status m) m ())-    -> FilePath-    -> Status m-emptyStatusWith _resolver _cacher rootDirectory = Status {..}+    :: 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 rootImport--    _dot = importNode (userNodeId 0) rootImport+    _stack = pure (Chained rootImport) -    _nextNodeId = 1+    _graph = []      _cache = Map.empty      _manager = Nothing -    _standardVersion = Dhall.Binary.defaultStandardVersion+    _substitutions = Dhall.Substitution.empty      _normalizer = Nothing      _startingContext = Dhall.Context.empty -    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-      }--importNode :: NodeId -> Import -> Dot NodeId-importNode nodeId i = do-    userNode-        nodeId-        [ ("label", Data.Text.unpack $ pretty i)-        , ("shape", "box")-        , ("style", "rounded")-        ]-    pure nodeId+    _semanticCacheMode = UseSemanticCache -stack :: Functor f => LensLike' f (Status m) (NonEmpty Import)-stack k s = fmap (\x -> s { _stack = x }) (k (_stack s))+    _cacheWarning = CacheNotWarned -dot :: Functor f => LensLike' f (Status m) (Dot NodeId)-dot k s = fmap (\x -> s { _dot = x }) (k (_dot s))+-- | Lens from a `Status` to its `_stack` field+stack :: Lens' Status (NonEmpty Chained)+stack = lens _stack (\s x -> s { _stack = x }) -nextNodeId :: Functor f => LensLike' f (Status m) Int-nextNodeId k s = fmap (\x -> s { _nextNodeId = x }) (k (_nextNodeId s))+-- | Lens from a `Status` to its `_graph` field+graph :: Lens' Status [Depends]+graph = lens _graph (\s x -> s { _graph = x }) -cache :: Functor f => LensLike' f (Status m) (Map Import (NodeId, Expr Src X))-cache k s = fmap (\x -> s { _cache = x }) (k (_cache s))+-- | Lens from a `Status` to its `_cache` field+cache :: Lens' Status (Map Chained ImportSemantics)+cache = lens _cache (\s x -> s { _cache = x }) -manager :: Functor f => LensLike' f (Status m) (Maybe Dynamic)-manager k s = fmap (\x -> s { _manager = x }) (k (_manager s))+-- | Lens from a `Status` to its `_remote` field+remote :: Lens' Status (URL -> StateT Status IO Data.Text.Text)+remote = lens _remote (\s x -> s { _remote = x }) -standardVersion :: Functor f => LensLike' f (Status m) StandardVersion-standardVersion k s =-    fmap (\x -> s { _standardVersion = x }) (k (_standardVersion s))+-- | 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 }) -normalizer :: Functor f => LensLike' f (Status m) (Maybe (ReifiedNormalizer X))-normalizer k s = fmap (\x -> s {_normalizer = x}) (k (_normalizer s))+-- | Lens from a `Status` to its `_substitutions` field+substitutions :: Lens' Status (Dhall.Substitution.Substitutions Src Void)+substitutions = lens _substitutions (\s x -> s { _substitutions = x }) -startingContext :: Functor f => LensLike' f (Status m) (Context (Expr Src X))-startingContext k s =-    fmap (\x -> s { _startingContext = x }) (k (_startingContext s))+-- | Lens from a `Status` to its `_normalizer` field+normalizer :: Lens' Status (Maybe (ReifiedNormalizer Void))+normalizer = lens _normalizer (\s x -> s {_normalizer = x}) -resolver-    :: Functor f-    => LensLike' f (Status m) (Import -> StateT (Status m) m Resolved)-resolver k s = fmap (\x -> s { _resolver = x }) (k (_resolver s))+-- | Lens from a `Status` to its `_startingContext` field+startingContext :: Lens' Status (Context (Expr Src Void))+startingContext = lens _startingContext (\s x -> s { _startingContext = x }) -cacher-    :: Functor f-    => LensLike' f (Status m) (Import -> Expr Src X -> StateT (Status m) m ())-cacher k s = fmap (\x -> s { _cacher = x }) (k (_cacher s))+-- | 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) @@ -193,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
@@ -1,61 +1,210 @@+{-# LANGUAGE NamedFieldPuns    #-}+{-# LANGUAGE OverloadedLists   #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternGuards     #-}+{-# LANGUAGE RecordWildCards   #-}+{-# LANGUAGE ViewPatterns      #-}+ -- | This module contains the implementation of the @dhall lint@ command  module Dhall.Lint     ( -- * Lint       lint-    , removeLetInLet     , removeUnusedBindings-    , optionalLitToSomeNone+    , fixAssert+    , fixParentPath+    , addPreludeExtensions+    , removeLetInLet+    , useToMap     ) where -import Control.Monad (mplus)-import Data.List.NonEmpty (NonEmpty(..))-import Data.Semigroup ((<>))-import Dhall.Core (Binding(..), Expr(..), Import, Var(..), subExpressions)+import Control.Applicative ((<|>)) -import qualified Dhall.Core-import qualified Dhall.Optics+import Dhall.Syntax+    ( Binding (..)+    , Chunks (..)+    , Directory (..)+    , Expr (..)+    , File (..)+    , FilePrefix (..)+    , Import (..)+    , ImportHashed (..)+    , ImportType (..)+    , URL (..)+    , Var (..)+    , subExpressions+    ) +import qualified Data.Foldable      as Foldable+import qualified Data.List.NonEmpty as NonEmpty+import qualified Data.Text          as Text+import qualified Dhall.Core         as Core+import qualified Dhall.Map+import qualified Lens.Micro         as Lens+ {-| Automatically improve a Dhall expression      Currently this: -    * removes unused @let@ bindings with 'removeLetInLet'.-    * consolidates nested @let@ bindings to use a multiple-@let@ binding with 'removeUnusedBindings'.-    * switches legacy @List@-like @Optional@ literals to use @Some@ / @None@ instead with 'optionalLitToSomeNone'+    * removes unused @let@ bindings with 'removeUnusedBindings'.+    * fixes @let a = x ≡ y@ to be @let a = assert : x ≡ y@+    * consolidates nested @let@ bindings to use a multiple-@let@ binding with 'removeLetInLet'+    * fixes paths of the form @.\/..\/foo@ to @..\/foo@ -}-lint :: Expr s Import -> Expr t Import-lint =-  Dhall.Optics.rewriteOf-    subExpressions-    ( \e ->-                removeLetInLet e-        `mplus` removeUnusedBindings e-        `mplus` optionalLitToSomeNone e-    )-    . Dhall.Core.denote--removeLetInLet :: Eq a => Expr s a -> Maybe (Expr s a)-removeLetInLet (Let a (Let b c)) = Just (Let (a <> b) c)-removeLetInLet _ = Nothing+lint :: Eq s => Expr s Import -> Expr s Import+lint =  Lens.rewriteOf subExpressions rewrite+  where+    rewrite e =+            fixAssert                e+        <|> removeUnusedBindings     e+        <|> fixParentPath            e+        <|> removeLetInLet           e+        <|> addPreludeExtensions     e +-- | Remove unused `Let` bindings. removeUnusedBindings :: Eq a => Expr s a -> Maybe (Expr s a)-removeUnusedBindings (Let (Binding a _ _ :| []) d)-    | not (V a 0 `Dhall.Core.freeIn` d) =-        Just d-    | otherwise =-        Nothing-removeUnusedBindings (Let (Binding a _ _ :| (l : ls)) d)-    | not (V a 0 `Dhall.Core.freeIn` e) =-        Just e-    | otherwise =-        Nothing-  where-    e = Let (l :| ls) d+-- Don't remove assertions!+removeUnusedBindings (Let (Binding _ _ _ _ _ e) _)+    | isOrContainsAssert e = Nothing+removeUnusedBindings (Let (Binding _ a _ _ _ _) d)+    | not (V a 0 `Core.freeIn` d) =+        Just (Core.shift (-1) (V a 0) d) removeUnusedBindings _ = Nothing +-- | Fix `Let` bindings  that the user probably meant to be @assert@s+fixAssert :: Expr s a -> Maybe (Expr s a)+fixAssert (Let (Binding { value = v@(Core.shallowDenote -> Equivalent {}), ..}) body) =+    Just (Let (Binding { value = Assert v, .. }) body)+fixAssert (Let binding body@(Core.shallowDenote -> Equivalent {})) =+    Just (Let binding (Assert body))+fixAssert _ =+    Nothing -optionalLitToSomeNone :: Expr s a -> Maybe (Expr s a)-optionalLitToSomeNone (OptionalLit _ (Just b)) = Just (Some b)-optionalLitToSomeNone (OptionalLit a Nothing) = Just (App None a)-optionalLitToSomeNone _ = Nothing+-- | This transforms @.\/..\/foo@ into @..\/foo@+fixParentPath :: Expr s Import -> Maybe (Expr s Import)+fixParentPath (Embed oldImport) = do+    let Import{..} = oldImport++    let ImportHashed{..} = importHashed++    case importType of+        Local Here File{ directory = Directory { components }, .. }+            | Just nonEmpty <- NonEmpty.nonEmpty components+            , NonEmpty.last nonEmpty == ".." -> do+                let newDirectory =+                        Directory { components = NonEmpty.init nonEmpty }++                let newImportType =+                        Local Parent File{ directory = newDirectory, .. }++                let newImportHashed =+                        ImportHashed { importType = newImportType, .. }++                let newImport = Import { importHashed = newImportHashed, .. }++                Just (Embed newImport)+        _ ->+            Nothing+fixParentPath _  = Nothing++{-| This transforms @https://prelude.dhall-lang.org/…/foo@ to+    @https://prelude.dhall-lang.org/…/foo.dhall@+-}+addPreludeExtensions :: Expr s Import -> Maybe (Expr s Import)+addPreludeExtensions (Embed oldImport) = do+    let Import{ importHashed = oldImportHashed, .. } = oldImport++    let ImportHashed{ importType = oldImportType, .. } = oldImportHashed++    case oldImportType of+        Remote URL{ path = oldPath, ..}+            | authority == "prelude.dhall-lang.org" ->+                case oldPath of+                    File{ file = oldFile, .. }+                        | not (Text.isSuffixOf ".dhall" oldFile) -> do+                            let newFile = oldFile <> ".dhall"++                            let newPath = File{ file = newFile, .. }++                            let newImportType = Remote URL{ path = newPath, .. }++                            let newImportHashed =+                                    ImportHashed{ importType = newImportType, .. }++                            let newImport =+                                    Import{ importHashed = newImportHashed, .. }++                            return (Embed newImport)+                    _ ->+                        Nothing+        _ -> do+            Nothing+addPreludeExtensions _ = Nothing++isOrContainsAssert :: Expr s a -> Bool+isOrContainsAssert (Assert _) = True+isOrContainsAssert e = Lens.anyOf subExpressions isOrContainsAssert e++-- | The difference between+--+-- > let x = 1 let y = 2 in x + y+--+-- and+--+-- > let x = 1 in let y = 2 in x + y+--+-- is that in the second expression, the inner 'Let' is wrapped by a 'Note'.+--+-- We remove such a 'Note' in order to consolidate nested let-blocks into a+-- single one.+removeLetInLet :: Expr s a -> Maybe (Expr s a)+removeLetInLet (Let binding (Note _ l@Let{})) = Just (Let binding l)+removeLetInLet _ = Nothing++-- | This replaces a record of key-value pairs with the equivalent use of+--   @toMap@+--+-- This is currently not used by @dhall lint@ because this would sort @Map@+-- keys, which is not necessarily a behavior-preserving change, but is still+-- made available as a convenient rewrite rule.  For example,+-- @{json,yaml}-to-dhall@ use this rewrite to simplify their output.+useToMap :: Expr s a -> Maybe (Expr s a)+useToMap+    (ListLit+        t@(Just+            (Core.shallowDenote -> App+                (Core.shallowDenote -> List)+                (Core.shallowDenote -> Record+                    (Dhall.Map.sort ->+                        [ ("mapKey", Core.shallowDenote . Core.recordFieldValue -> Text)+                        , ("mapValue", _)+                        ]+                    )+                )+            )+        )+        []+    ) =+        Just (ToMap (RecordLit []) t)+useToMap (ListLit _ keyValues)+    | not (null keyValues)+    , Just keyValues' <- traverse convert keyValues =+        Just+            (ToMap+                (RecordLit (Dhall.Map.fromList (Foldable.toList keyValues')))+                Nothing+            )+  where+    convert keyValue =+        case Core.shallowDenote keyValue of+            RecordLit+                (Dhall.Map.sort ->+                    [ ("mapKey"  , Core.shallowDenote . Core.recordFieldValue -> TextLit (Chunks [] key))+                    , ("mapValue", value)+                    ]+                ) ->+                    Just (key, value)+            _ ->+                Nothing+useToMap _ =+    Nothing
src/Dhall/Main.hs view
@@ -2,7 +2,8 @@     @dhall@ executable -} -{-# LANGUAGE DeriveAnyClass    #-}+{-# LANGUAGE ApplicativeDo     #-}+{-# LANGUAGE LambdaCase        #-} {-# LANGUAGE NamedFieldPuns    #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards   #-}@@ -11,99 +12,192 @@     ( -- * Options       Options(..)     , Mode(..)+    , ResolveMode(..)     , parseOptions     , parserInfoOptions        -- * Execution-    , command+    , Dhall.Main.command     , main     ) where  import Control.Applicative (optional, (<|>))-import Control.Exception (SomeException)-import Data.Monoid ((<>))-import Data.Text (Text)-import Data.Text.Prettyprint.Doc (Doc, Pretty)-import Data.Version (showVersion)-import Dhall.Binary (StandardVersion)-import Dhall.Core (Expr(..), Import)-import Dhall.Freeze (Intent(..), Scope(..))-import Dhall.Import (Imported(..))-import Dhall.Parser (Src)-import Dhall.Pretty (Ann, CharacterSet(..), annToAnsiStyle, layoutOpts)-import Dhall.TypeCheck (DetailedTypeError(..), TypeError, X)-import Lens.Family (set)+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 (exitFailure)-import System.IO (Handle)+import Prettyprinter       (Doc, Pretty)+import System.Exit         (ExitCode, exitFailure)+import System.IO           (Handle)+import Text.Dot            ((.->.)) +import Dhall.Core+    ( Expr (Annot)+    , Import (..)+    , ImportHashed (..)+    , ImportType (..)+    , URL (..)+    , pretty+    )+import Dhall.Util+    ( Censor (..)+    , CheckFailed (..)+    , Header (..)+    , Input (..)+    , Output (..)+    , OutputMode (..)+    , Transitivity (..)+    , handleMultipleChecksFailed+    )+ import qualified Codec.CBOR.JSON import qualified Codec.CBOR.Read import qualified Codec.CBOR.Write-import qualified Codec.Serialise 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 import qualified Data.ByteString.Lazy.Char8+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 Dhall import qualified Dhall.Binary import qualified Dhall.Core import qualified Dhall.Diff+import qualified Dhall.DirectoryTree                as DirectoryTree import qualified Dhall.Format import qualified Dhall.Freeze-import qualified Dhall.Hash import qualified Dhall.Import import qualified Dhall.Import.Types import qualified Dhall.Lint-import qualified Dhall.Parser+import qualified Dhall.Map+import qualified Dhall.Package import qualified Dhall.Pretty import qualified Dhall.Repl+import qualified Dhall.Schemas+import qualified Dhall.Tags import qualified Dhall.TypeCheck+import qualified Dhall.Util import qualified GHC.IO.Encoding import qualified Options.Applicative-import qualified Paths_dhall as Meta+import qualified Prettyprinter                      as Pretty+import qualified Prettyprinter.Render.Terminal      as Pretty+import qualified Prettyprinter.Render.Text          as Pretty.Text+import qualified System.AtomicWrite.Writer.LazyText as AtomicWrite.LazyText import qualified System.Console.ANSI+import qualified System.Exit                        as Exit+import qualified System.FilePath import qualified System.IO import qualified Text.Dot-import qualified Data.Map+import qualified Text.Pretty.Simple  -- | Top-level program options data Options = Options-    { mode            :: Mode-    , explain         :: Bool-    , plain           :: Bool-    , ascii           :: Bool-    , standardVersion :: StandardVersion+    { mode               :: Mode+    , explain            :: Bool+    , plain              :: Bool+    , chosenCharacterSet :: Maybe CharacterSet+    , censor             :: Censor     }  -- | The subcommands for the @dhall@ executable data Mode-    = Default { file :: Maybe FilePath, annotate :: Bool, alpha :: Bool }+    = Default+          { file :: Input+          , output :: Output+          , annotate :: Bool+          , alpha :: Bool+          , semanticCacheMode :: SemanticCacheMode+          , version :: Bool+          }     | Version-    | Resolve { file :: Maybe FilePath, resolveMode :: Maybe ResolveMode }-    | Type { file :: Maybe FilePath }-    | Normalize { file :: Maybe FilePath, alpha :: Bool }+    | Resolve+          { file :: Input+          , resolveMode :: Maybe ResolveMode+          , semanticCacheMode :: SemanticCacheMode+          }+    | Type+          { file :: Input+          , quiet :: Bool+          , semanticCacheMode :: SemanticCacheMode+          }+    | Normalize { file :: Input , alpha :: Bool }     | Repl-    | Format { formatMode :: Dhall.Format.FormatMode }-    | Freeze { inplace :: Maybe FilePath, all_ :: Bool, cache :: Bool }-    | Hash+    | 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 { inplace :: Maybe FilePath }-    | Encode { file :: Maybe FilePath, json :: Bool }-    | Decode { file :: Maybe FilePath, json :: Bool }+    | Lint { deprecatedInPlace :: Bool, transitivity :: Transitivity, outputMode :: OutputMode, inputs :: NonEmpty Input }+    | Tags+          { input :: Input+          , output :: Output+          , suffixes :: Maybe [Text]+          , followSymlinks :: Bool+          }+    | Encode { file :: Input, json :: Bool }+    | Decode { file :: Input, json :: Bool, quiet :: Bool }+    | Text { file :: Input, output :: Output }+    | DirectoryTree { allowSeparators :: Bool, file :: Input, path :: FilePath }+    | Schemas { file :: Input, outputMode :: OutputMode, schemas :: Text }+    | SyntaxTree { file :: Input, noted :: Bool }+    | Package+        { packageOptions :: Endo Dhall.Package.Options+        , packageFiles :: NonEmpty FilePath+        } +-- | This specifies how to resolve transitive dependencies data ResolveMode     = Dot+    -- ^ Generate a DOT file for @graphviz@     | ListTransitiveDependencies+    -- ^ List all transitive dependencies as text, one per line     | ListImmediateDependencies+    -- ^ List immediate dependencies as text, one per line +-- | Groups of subcommands+data Group+    = Manipulate+    | Generate+    | Interpret+    | Convert+    | Miscellaneous+    | Debugging +groupDescription :: Group -> String+groupDescription group = case group of+    Manipulate -> "Manipulate Dhall code"+    Generate -> "Generate other formats from Dhall"+    Interpret -> "Interpret Dhall"+    Convert -> "Convert Dhall to and from its binary representation"+    Miscellaneous -> "Miscellaneous"+    Debugging -> "Debugging this interpreter"+ -- | `Parser` for the `Options` type parseOptions :: Parser Options parseOptions =@@ -111,8 +205,8 @@     <$> parseMode     <*> switch "explain" "Explain error messages in more detail"     <*> switch "plain" "Disable syntax highlighting"-    <*> switch "ascii" "Format code using only ASCII syntax"-    <*> Dhall.Binary.parseStandardVersion+    <*> parseCharacterSet+    <*> parseCensor   where     switch name description =         Options.Applicative.switch@@ -120,11 +214,30 @@             <>  Options.Applicative.help description             ) -subcommand :: String -> String -> Parser a -> Parser a-subcommand name description parser =+    parseCensor = fmap f (switch "censor" "Hide source code in error messages")+      where+        f True  = Censor+        f False = NoCensor++    parseCharacterSet =+            Options.Applicative.flag'+                (Just Unicode)+                (   Options.Applicative.long "unicode"+                <>  Options.Applicative.help "Format code using only Unicode syntax"+                )+        <|> Options.Applicative.flag'+                (Just ASCII)+                (   Options.Applicative.long "ascii"+                <>  Options.Applicative.help "Format code using only ASCII syntax"+                )+        <|> pure Nothing++subcommand :: Group -> String -> String -> Parser a -> Parser a+subcommand group name description parser =     Options.Applicative.hsubparser         (   Options.Applicative.command name parserInfo         <>  Options.Applicative.metavar name+        <>  Options.Applicative.commandGroup (groupDescription group)         )   where     parserInfo =@@ -136,67 +249,154 @@ parseMode :: Parser Mode parseMode =         subcommand-            "version"-            "Display version"-            (pure Version)+            Manipulate+            "format"+            "Standard code formatter for the Dhall language"+            (Format <$> deprecatedInPlace <*> parseTransitiveSwitch <*> parseCheck "formatted" <*> parseFiles)     <|> subcommand+            Manipulate+            "freeze"+            "Add integrity checks to remote import statements of an expression"+            (Freeze <$> deprecatedInPlace <*> parseTransitiveSwitch <*> parseAllFlag <*> parseCacheFlag <*> parseCheck "frozen" <*> parseFiles)+    <|> subcommand+            Manipulate+            "lint"+            "Improve Dhall code by using newer language features and removing dead code"+            (Lint <$> deprecatedInPlace <*> parseTransitiveSwitch <*> parseCheck "linted" <*> parseFiles)+    <|> subcommand+            Manipulate+            "rewrite-with-schemas"+            "Simplify Dhall code using a schemas record"+            (Dhall.Main.Schemas <$> parseInplaceNonTransitive <*> parseCheck "rewritten" <*> parseSchemasRecord)+    <|> subcommand+            Generate+            "text"+            "Render a Dhall expression that evaluates to a Text literal"+            (Text <$> parseFile <*> parseOutput)+    <|> subcommand+            Generate+            "to-directory-tree"+            "Convert nested records of Text literals into a directory tree"+            (DirectoryTree <$> parseDirectoryTreeAllowSeparators <*> parseFile <*> parseDirectoryTreeOutput)+    <|> subcommand+            Interpret             "resolve"             "Resolve an expression's imports"-            (Resolve <$> optional parseFile <*> parseResolveMode)+            (Resolve <$> parseFile <*> parseResolveMode <*> parseSemanticCacheMode)     <|> subcommand+            Interpret             "type"             "Infer an expression's type"-            (Type <$> optional parseFile)+            (Type <$> parseFile <*> parseQuiet <*> parseSemanticCacheMode)     <|> subcommand+            Interpret             "normalize"             "Normalize an expression"-            (Normalize <$> optional parseFile <*> parseAlpha)+            (Normalize <$> parseFile <*> parseAlpha)     <|> subcommand+            Convert+            "encode"+            "Encode a Dhall expression to binary"+            (Encode <$> parseFile <*> parseJSONFlag)+    <|> subcommand+            Convert+            "decode"+            "Decode a Dhall expression from binary"+            (Decode <$> parseFile <*> parseJSONFlag <*> parseQuiet)+    <|> subcommand+            Miscellaneous             "repl"             "Interpret expressions in a REPL"             (pure Repl)     <|> subcommand+            Miscellaneous             "diff"             "Render the difference between the normal form of two expressions"             (Diff <$> argument "expr1" <*> argument "expr2")     <|> subcommand+            Miscellaneous             "hash"             "Compute semantic hashes for Dhall expressions"-            (pure Hash)-    <|> subcommand-            "lint"-            "Improve Dhall code"-            (Lint <$> optional parseInplace)+            (Hash <$> parseFile <*> parseCache)     <|> subcommand-            "format"-            "Formatter for the Dhall language"-            (Format <$> parseFormatMode)+            Miscellaneous+            "package"+            "Create a package.dhall referencing the provided paths"+            (Package <$> parsePackageOptions <*> parsePackageFiles)     <|> subcommand-            "freeze"-            "Add integrity checks to remote import statements of an expression"-            (Freeze <$> optional parseInplace <*> parseAllFlag <*> parseCacheFlag)+            Miscellaneous+            "tags"+            "Generate etags file"+            (Tags <$> parseInput <*> parseTagsOutput <*> parseSuffixes <*> parseFollowSymlinks)     <|> subcommand-            "encode"-            "Encode a Dhall expression to binary"-            (Encode <$> optional parseFile <*> parseJSONFlag)+            Miscellaneous+            "version"+            "Display version"+            (pure Version)     <|> subcommand-            "decode"-            "Decode a Dhall expression from binary"-            (Decode <$> optional parseFile <*> parseJSONFlag)-    <|> (Default <$> optional parseFile <*> parseAnnotate <*> parseAlpha)+            Debugging+            "haskell-syntax-tree"+            "Output the parsed syntax tree (for debugging)"+            (SyntaxTree <$> parseFile <*> parseNoted)+    <|> (   Default+        <$> parseFile+        <*> parseOutput+        <*> parseAnnotate+        <*> parseAlpha+        <*> parseSemanticCacheMode+        <*> parseVersion+        )   where+    deprecatedInPlace =+        Options.Applicative.switch+            (   Options.Applicative.long "inplace"+            <>  Options.Applicative.internal -- completely hidden from help+            )+     argument =             fmap Data.Text.pack         .   Options.Applicative.strArgument         .   Options.Applicative.metavar -    parseFile =-        Options.Applicative.strOption-            (   Options.Applicative.long "file"-            <>  Options.Applicative.help "Read expression from a file instead of standard input"-            <>  Options.Applicative.metavar "FILE"-            )+    parseFile = fmap f (optional p)+      where+        f  Nothing    = StandardInput+        f (Just file) = InputFile file +        p = Options.Applicative.strOption+                (   Options.Applicative.long "file"+                <>  Options.Applicative.help "Read expression from a file instead of standard input"+                <>  Options.Applicative.metavar "FILE"+                <>  Options.Applicative.action "file"+                )++    parseFiles = fmap f (Options.Applicative.many p)+      where+        -- Parse explicit stdin in the input filepaths+        parseStdin inputs+            | InputFile "-" `elem` inputs = StandardInput : filter (/= InputFile "-") inputs+            | otherwise = inputs++        f = fromMaybe (pure StandardInput) . nonEmpty . parseStdin . fmap InputFile++        p = Options.Applicative.strArgument+                (   Options.Applicative.help "Read expression from files instead of standard input"+                <>  Options.Applicative.metavar "FILES"+                <>  Options.Applicative.action "file"+                )++    parseOutput = fmap f (optional p)+      where+        f Nothing = StandardOutput+        f (Just file) = OutputFile file++        p = Options.Applicative.strOption+                (   Options.Applicative.long "output"+                <>  Options.Applicative.help "Write result to a file instead of standard output"+                <>  Options.Applicative.metavar "FILE"+                <>  Options.Applicative.action "file"+                )+     parseAlpha =         Options.Applicative.switch             (   Options.Applicative.long "alpha"@@ -209,6 +409,21 @@             <>  Options.Applicative.help "Add a type annotation to the output"             ) +    parseSemanticCacheMode =+        Options.Applicative.flag+            UseSemanticCache+            IgnoreSemanticCache+            (   Options.Applicative.long "no-cache"+            <>  Options.Applicative.help+                  "Handle protected imports as if the cache was empty"+            )++    parseVersion =+        Options.Applicative.switch+            (   Options.Applicative.long "version"+            <>  Options.Applicative.help "Display version"+            )+     parseResolveMode =           Options.Applicative.flag' (Just Dot)               (   Options.Applicative.long "dot"@@ -225,17 +440,76 @@           Options.Applicative.flag' (Just ListTransitiveDependencies)               (   Options.Applicative.long "transitive-dependencies"               <>  Options.Applicative.help-                    "List transitive import dependencies"+                    "List transitive import dependencies in post-order"               )         <|> pure Nothing +    parseQuiet =+        Options.Applicative.switch+            (   Options.Applicative.long "quiet"+            <>  Options.Applicative.help "Don't print the result"+            )+     parseInplace =         Options.Applicative.strOption-        (   Options.Applicative.long "inplace"-        <>  Options.Applicative.help "Modify the specified file in-place"-        <>  Options.Applicative.metavar "FILE"+            (   Options.Applicative.long "inplace"+            <>  Options.Applicative.help "Modify the specified file in-place"+            <>  Options.Applicative.metavar "FILE"+            <>  Options.Applicative.action "file"+            )++    parseTransitiveSwitch = Options.Applicative.flag NonTransitive Transitive+        (   Options.Applicative.long "transitive"+        <>  Options.Applicative.help "Modify the input and its transitive relative imports in-place"         ) +    parseInplaceNonTransitive =+            fmap InputFile parseInplace+        <|> pure StandardInput++    parseInput = fmap f (optional p)+      where+        f  Nothing    = StandardInput+        f (Just path) = InputFile path++        p = Options.Applicative.strOption+            (   Options.Applicative.long "path"+            <>  Options.Applicative.help "Index all files in path recursively. Will get list of files from STDIN if omitted."+            <>  Options.Applicative.metavar "PATH"+            <>  Options.Applicative.action "file"+            <>  Options.Applicative.action "directory"+            )++    parseTagsOutput = fmap f (optional p)+      where+        f  Nothing    = OutputFile "tags"+        f (Just file) = OutputFile file++        p = Options.Applicative.strOption+            (   Options.Applicative.long "output"+            <>  Options.Applicative.help "The name of the file that the tags are written to. Defaults to \"tags\""+            <>  Options.Applicative.metavar "FILENAME"+            <>  Options.Applicative.action "file"+            )++    parseSuffixes = fmap f (optional p)+      where+        f  Nothing    = Just [".dhall"]+        f (Just "")   = Nothing+        f (Just line) = Just (Data.Text.splitOn " " line)++        p = Options.Applicative.strOption+            (   Options.Applicative.long "suffixes"+            <>  Options.Applicative.help "Index only files with suffixes. \"\" to index all files."+            <>  Options.Applicative.metavar "SUFFIXES"+            )++    parseFollowSymlinks =+        Options.Applicative.switch+        (   Options.Applicative.long "follow-symlinks"+        <>  Options.Applicative.help "Follow symlinks when recursing directories"+        )+     parseJSONFlag =         Options.Applicative.switch         (   Options.Applicative.long "json"@@ -245,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 =@@ -254,27 +528,77 @@         <>  Options.Applicative.help "Add fallback unprotected imports when using integrity checks purely for caching purposes"         ) -    parseCheck =+    parseCheck processed = fmap adapt switch+      where+        adapt True  = Check+        adapt False = Write++        switch =+            Options.Applicative.switch+            (   Options.Applicative.long "check"+            <>  Options.Applicative.help ("Only check if the input is " <> processed)+            )++    parseSchemasRecord =+        Options.Applicative.strOption+            (   Options.Applicative.long "schemas"+            <>  Options.Applicative.help "A record of schemas"+            <>  Options.Applicative.metavar "EXPR"+            )++    parseDirectoryTreeAllowSeparators =         Options.Applicative.switch-        (   Options.Applicative.long "check"-        <>  Options.Applicative.help "Only check if the input is formatted"-        )+            (   Options.Applicative.long "allow-path-separators"+            <>  Options.Applicative.help "Whether to allow path separators in file names"+            ) -    parseFormatMode = adapt <$> parseCheck <*> optional parseInplace-      where-        adapt True  path    = Dhall.Format.Check {..}-        adapt False inplace = Dhall.Format.Modify {..}+    parseDirectoryTreeOutput =+        Options.Applicative.strOption+            (   Options.Applicative.long "output"+            <>  Options.Applicative.help "The destination path to create"+            <>  Options.Applicative.metavar "PATH"+            <>  Options.Applicative.action "directory"+            ) -getExpression :: Maybe FilePath -> IO (Expr Src Import)-getExpression maybeFile = do-    inText <- do-        case maybeFile of-            Just "-"  -> Data.Text.IO.getContents-            Just file -> Data.Text.IO.readFile file-            Nothing   -> Data.Text.IO.getContents+    parseNoted =+        Options.Applicative.switch+            (   Options.Applicative.long "noted"+            <>  Options.Applicative.help "Print `Note` constructors"+            ) -    Dhall.Core.throws (Dhall.Parser.exprFromText "(stdin)" inText)+    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 =@@ -284,40 +608,69 @@         <>  Options.Applicative.fullDesc         ) +noHeaders :: Import -> Import+noHeaders+    (Import { importHashed = ImportHashed { importType = Remote URL{ .. }, ..}, .. }) =+    Import { importHashed = ImportHashed { importType = Remote URL{ headers = Nothing, .. }, .. }, .. }+noHeaders i =+    i+ -- | Run the command specified by the `Options` type command :: Options -> IO () command (Options {..}) = do-    let characterSet = case ascii of-            True  -> ASCII-            False -> Unicode-     GHC.IO.Encoding.setLocaleEncoding System.IO.utf8 -    let toStatus maybeFile =-            set Dhall.Import.standardVersion standardVersion-                (Dhall.Import.emptyStatus file)-          where-            file = case maybeFile of-                Just "-" -> "."-                Just f   -> f-                Nothing  -> "."+    let rootDirectory = \case+            InputFile f   -> System.FilePath.takeDirectory f+            StandardInput -> "." -    let handle =-                Control.Exception.handle handler2-            .   Control.Exception.handle handler1-            .   Control.Exception.handle handler0+    let toStatus = Dhall.Import.emptyStatus . rootDirectory++    let getExpression = Dhall.Util.getExpression censor++    -- The characterSet detection used here only works on the source+    -- expression, before any transformation is applied. This helper is there+    -- make sure the detection is done on the correct expr.+    let getExpressionAndCharacterSet file = do+            expr <- getExpression file++            let characterSet = fromMaybe (detectCharacterSet expr) chosenCharacterSet++            return (expr, characterSet)++    let handle io =+            Control.Exception.catches io+                [ Handler handleTypeError+                , Handler handleImported+                , Handler handleExitCode+                ]           where-            handler0 e = do-                let _ = e :: TypeError Src X+            handleAll e = do+                let string = show (e :: SomeException)++                if not (null string)+                    then System.IO.hPutStrLn System.IO.stderr string+                    else return ()++                System.Exit.exitFailure++            handleTypeError e = Control.Exception.handle handleAll $ do+                let _ = e :: TypeError Src Void                 System.IO.hPutStrLn System.IO.stderr ""                 if explain-                    then Control.Exception.throwIO (DetailedTypeError e)+                    then+                        case censor of+                            Censor   -> Control.Exception.throwIO (CensoredDetailed (DetailedTypeError e))+                            NoCensor -> Control.Exception.throwIO (DetailedTypeError e)+                     else do                         Data.Text.IO.hPutStrLn System.IO.stderr "\ESC[2mUse \"dhall --explain\" for detailed errors\ESC[0m"-                        Control.Exception.throwIO e+                        case censor of+                            Censor   -> Control.Exception.throwIO (Censored e)+                            NoCensor -> Control.Exception.throwIO e -            handler1 (Imported ps e) = do-                let _ = e :: TypeError Src X+            handleImported (Imported ps e) = Control.Exception.handle handleAll $ do+                let _ = e :: TypeError Src Void                 System.IO.hPutStrLn System.IO.stderr ""                 if explain                     then Control.Exception.throwIO (Imported ps (DetailedTypeError e))@@ -325,18 +678,12 @@                         Data.Text.IO.hPutStrLn System.IO.stderr "\ESC[2mUse \"dhall --explain\" for detailed errors\ESC[0m"                         Control.Exception.throwIO (Imported ps e) -            handler2 e = do-                let string = show (e :: SomeException)--                if not (null string)-                    then System.IO.hPutStrLn System.IO.stderr string-                    else return ()--                System.Exit.exitFailure+            handleExitCode e =+                Control.Exception.throwIO (e :: ExitCode)      let renderDoc :: Handle -> Doc Ann -> IO ()         renderDoc h doc = do-            let stream = Pretty.layoutSmart layoutOpts doc+            let stream = Dhall.Pretty.layout doc              supportsANSI <- System.Console.ANSI.hSupportsANSI h             let ansiStream =@@ -347,28 +694,34 @@             Pretty.renderIO h ansiStream             Data.Text.IO.hPutStrLn h "" -    let render :: Pretty a => Handle -> Expr s 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 -    handle $ case mode of-        Version -> do-            let line₀ = "Haskell package version: "-                    <>  Data.Text.pack (showVersion Meta.version)+    let writeDocToFile :: FilePath -> Doc ann -> IO ()+        writeDocToFile file doc = do+            let stream = Dhall.Pretty.layout (doc <> "\n") -            let line₁ = "Standard version: "-                    <>  Dhall.Binary.renderStandardVersion Dhall.Binary.defaultStandardVersion+            AtomicWrite.LazyText.atomicWriteFile file (Pretty.Text.renderLazy stream) -            Data.Text.IO.putStrLn line₀-            Data.Text.IO.putStrLn line₁+    handle $ case mode of+        Version ->+            putStrLn dhallVersionString          Default {..} -> do-            expression <- getExpression file+            if version+                then do+                    putStrLn dhallVersionString+                    Exit.exitSuccess+                else return () -            resolvedExpression <- State.evalStateT (Dhall.Import.loadWith expression) (toStatus file)+            (expression, characterSet) <- getExpressionAndCharacterSet file +            resolvedExpression <-+                Dhall.Import.loadRelativeTo (rootDirectory file) semanticCacheMode expression+             inferredType <- Dhall.Core.throws (Dhall.TypeCheck.typeOf resolvedExpression)              let normalizedExpression = Dhall.Core.normalize resolvedExpression@@ -383,47 +736,75 @@                         then Annot alphaNormalizedExpression inferredType                         else alphaNormalizedExpression -            render System.IO.stdout annotatedExpression+            case output of+                StandardOutput -> render System.IO.stdout characterSet annotatedExpression +                OutputFile file_ ->+                    writeDocToFile+                        file_+                        (Dhall.Pretty.prettyCharacterSet characterSet annotatedExpression)+         Resolve { resolveMode = Just Dot, ..} -> do             expression <- getExpression file -            (Dhall.Import.Types.Status { _dot}) <--                State.execStateT (Dhall.Import.loadWith expression) (toStatus file)+            (Dhall.Import.Types.Status { _graph, _stack }) <-+                State.execStateT (Dhall.Import.loadWith expression) (toStatus file) { _semanticCacheMode = semanticCacheMode } -            putStr . ("strict " <>) . Text.Dot.showDot $-                   Text.Dot.attribute ("rankdir", "LR") >>-                   _dot+            let (rootImport :| _) = _stack+                imports = rootImport : map parent _graph ++ map child _graph+                importIds = Data.Map.fromList (zip imports [Text.Dot.userNodeId i | i <- [0..]]) +            let dotNode (i, nodeId) =+                    Text.Dot.userNode+                        nodeId+                        [ ("label", Data.Text.unpack $ pretty (convert i))+                        , ("shape", "box")+                        , ("style", "rounded")+                        ]+                  where+                    convert = noHeaders . Dhall.Import.chainedImport++            let dotEdge (Depends parent child) =+                    case (Data.Map.lookup parent importIds, Data.Map.lookup child importIds) of+                        (Just from, Just to) -> from .->. to+                        _                    -> pure ()++            let dot = do Text.Dot.attribute ("rankdir", "LR")+                         mapM_ dotNode (Data.Map.assocs importIds)+                         mapM_ dotEdge _graph++            putStr . ("strict " <>) . Text.Dot.showDot $ dot+         Resolve { resolveMode = Just ListImmediateDependencies, ..} -> do             expression <- getExpression file -            mapM_ (print-                        . Pretty.pretty-                        . Dhall.Core.importHashed) expression+            mapM_ (print . Pretty.pretty . noHeaders) expression          Resolve { resolveMode = Just ListTransitiveDependencies, ..} -> do             expression <- getExpression file              (Dhall.Import.Types.Status { _cache }) <--                State.execStateT (Dhall.Import.loadWith expression) (toStatus file)+                State.execStateT (Dhall.Import.loadWith expression) (toStatus file) { _semanticCacheMode = semanticCacheMode }              mapM_ print-                 .   fmap (   Pretty.pretty-                          .   Dhall.Core.importType-                          .   Dhall.Core.importHashed )-                 .   Data.Map.keys+                 .   fmap ( Pretty.pretty+                          . noHeaders+                          . Dhall.Import.chainedImport+                          )+                 .   reverse+                 .   Dhall.Map.keys                  $   _cache          Resolve { resolveMode = Nothing, ..} -> do-            expression <- getExpression file+            (expression, characterSet) <- getExpressionAndCharacterSet file -            (resolvedExpression, _) <--                State.runStateT (Dhall.Import.loadWith expression) (toStatus file)-            render System.IO.stdout resolvedExpression+            resolvedExpression <-+                Dhall.Import.loadRelativeTo (rootDirectory file) semanticCacheMode expression +            render System.IO.stdout characterSet resolvedExpression+         Normalize {..} -> do-            expression <- getExpression file+            (expression, characterSet) <- getExpressionAndCharacterSet file              resolvedExpression <- Dhall.Import.assertNoImports expression @@ -436,19 +817,24 @@                     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.assertNoImports expression+            resolvedExpression <-+                Dhall.Import.loadRelativeTo (rootDirectory file) semanticCacheMode expression              inferredType <- Dhall.Core.throws (Dhall.TypeCheck.typeOf resolvedExpression) -            render System.IO.stdout (Dhall.Core.normalize inferredType)+            if quiet+                then return ()+                else render System.IO.stdout characterSet inferredType -        Repl -> do-            Dhall.Repl.repl characterSet explain standardVersion+        Repl ->+            Dhall.Repl.repl+                (fromMaybe Unicode chosenCharacterSet) -- Default to Unicode if no characterSet specified+                explain          Diff {..} -> do             expression1 <- Dhall.inputExpr expr1@@ -457,54 +843,116 @@              let diff = Dhall.Diff.diffNormalized expression1 expression2 -            renderDoc System.IO.stdout diff+            renderDoc System.IO.stdout (Dhall.Diff.doc diff) +            if Dhall.Diff.same diff+                then return ()+                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 inplace scope intent characterSet standardVersion+            Dhall.Freeze.freeze outputMode transitivity inputs scope intent chosenCharacterSet censor -        Hash -> do-            Dhall.Hash.hash standardVersion+        Hash {..} -> do+            expression <- getExpression file -        Lint {..} -> do-            case inplace of-                Just file -> do-                    text <- Data.Text.IO.readFile file+            resolvedExpression <-+                Dhall.Import.loadRelativeTo (rootDirectory file) UseSemanticCache expression -                    (header, expression) <- Dhall.Core.throws (Dhall.Parser.exprAndHeaderFromText file text)+            _ <- Dhall.Core.throws (Dhall.TypeCheck.typeOf resolvedExpression) -                    let lintedExpression = Dhall.Lint.lint expression+            let normalizedExpression =+                    Dhall.Core.alphaNormalize (Dhall.Core.normalize resolvedExpression) -                    let doc =   Pretty.pretty header-                            <>  Dhall.Pretty.prettyCharacterSet characterSet lintedExpression+            if cache+                then Dhall.Import.writeExpressionToSemanticCache normalizedExpression+                else return () -                    System.IO.withFile file System.IO.WriteMode (\h -> do-                        renderDoc h doc )+            Data.Text.IO.putStrLn (Dhall.Import.hashExpressionToCode normalizedExpression) -                Nothing -> do-                    text <- Data.Text.IO.getContents+        Lint { transitivity = transitivity0, ..} -> do+            when deprecatedInPlace $+                System.IO.hPutStrLn System.IO.stderr "Warning: the flag \"--inplace\" is deprecated" -                    (header, expression) <- Dhall.Core.throws (Dhall.Parser.exprAndHeaderFromText "(stdin)" text)+            handleMultipleChecksFailed "lint" "linted" go inputs+          where+            go input = do+                let directory = case input of+                        StandardInput  -> "."+                        InputFile file -> System.FilePath.takeDirectory file -                    let lintedExpression = Dhall.Lint.lint expression+                let status = Dhall.Import.emptyStatus directory -                    let doc =   Pretty.pretty header-                            <>  Dhall.Pretty.prettyCharacterSet characterSet lintedExpression+                (inputName, originalText, transitivity) <- case input of+                    InputFile file -> do+                        text <- Data.Text.IO.readFile file -                    renderDoc System.IO.stdout doc+                        return (file, text, transitivity0)+                    StandardInput -> do+                        text <- Data.Text.IO.getContents +                        return ("(input)", text, NonTransitive)++                (Header header, parsedExpression) <-+                    Dhall.Util.getExpressionAndHeaderFromStdinText censor inputName originalText++                let characterSet = fromMaybe (detectCharacterSet parsedExpression) chosenCharacterSet++                case transitivity of+                    Transitive ->+                        for_ parsedExpression $ \import_ -> do+                            maybeFilepath <- Dhall.Import.dependencyToFile status import_++                            for_ maybeFilepath $ \filepath ->+                                go (InputFile filepath)++                    NonTransitive ->+                        return ()++                let lintedExpression = Dhall.Lint.lint parsedExpression++                let doc =   Pretty.pretty header+                        <>  Dhall.Pretty.prettyCharacterSet characterSet lintedExpression++                let stream = Dhall.Pretty.layout doc++                let modifiedText = Pretty.Text.renderStrict stream <> "\n"++                case outputMode of+                    Write -> do+                        case input of+                            InputFile file ->+                                if originalText == modifiedText+                                    then return ()+                                    else writeDocToFile file doc++                            StandardInput ->+                                renderDoc System.IO.stdout doc++                        return (Right ())++                    Check ->+                        return $+                            if originalText == modifiedText+                                then Right ()+                                else Left CheckFailed{..}+         Encode {..} -> do             expression <- getExpression file -            let term = Dhall.Binary.encode expression--            let bytes = Codec.Serialise.serialise term+            let bytes = Dhall.Binary.encodeExpression (Dhall.Core.denote expression)              if json                 then do@@ -516,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-                    Just f  -> Data.ByteString.Lazy.readFile f-                    Nothing -> Data.ByteString.Lazy.getContents+                    InputFile f   -> Data.ByteString.Lazy.readFile f+                    StandardInput -> Data.ByteString.Lazy.getContents -            term <- do+            expression <-                 if json                     then do                         value <- case Data.Aeson.eitherDecode' bytes of@@ -534,19 +982,92 @@                          let encoding = Codec.CBOR.JSON.encodeValue value -                        let cborBytes = Codec.CBOR.Write.toLazyByteString encoding-                        Dhall.Core.throws (Codec.Serialise.deserialiseOrFail cborBytes)-                    else do-                        Dhall.Core.throws (Codec.Serialise.deserialiseOrFail bytes)+                        let cborgBytes = Codec.CBOR.Write.toLazyByteString encoding -            expression <- Dhall.Core.throws (Dhall.Binary.decodeExpression term)+                        Dhall.Core.throws (Dhall.Binary.decodeExpression cborgBytes)+                    else+                        Dhall.Core.throws (Dhall.Binary.decodeExpression bytes) -            let doc = Dhall.Pretty.prettyCharacterSet characterSet expression -            renderDoc System.IO.stdout doc+            if quiet+                then return ()+                else do+                    let doc =+                            Dhall.Pretty.prettyCharacterSet+                                (fromMaybe Unicode chosenCharacterSet) -- default to Unicode+                                (Dhall.Core.renote expression :: Expr Src Import) +                    renderDoc System.IO.stdout doc++        Text {..} -> do+            expression <- getExpression file++            resolvedExpression <-+                Dhall.Import.loadRelativeTo (rootDirectory file) UseSemanticCache expression++            _ <- Dhall.Core.throws (Dhall.TypeCheck.typeOf (Annot resolvedExpression Dhall.Core.Text))++            let normalizedExpression = Dhall.Core.normalize resolvedExpression++            case normalizedExpression of+                Dhall.Core.TextLit (Dhall.Core.Chunks [] text) ->+                    let write = case output of+                          StandardOutput -> Data.Text.IO.putStr+                          OutputFile file_ -> Data.Text.IO.writeFile file_+                    in write text+                _ -> do+                    let invalidDecoderExpected :: Expr Void Void+                        invalidDecoderExpected = Dhall.Core.Text++                    let invalidDecoderExpression :: Expr Void Void+                        invalidDecoderExpression = normalizedExpression++                    Control.Exception.throwIO (Dhall.InvalidDecoder {..})++        Tags {..} -> do+            tags <- Dhall.Tags.generate input suffixes followSymlinks++            case output of+                OutputFile file ->+                    System.IO.withFile file System.IO.WriteMode (`Data.Text.IO.hPutStr` tags)++                StandardOutput -> Data.Text.IO.putStrLn tags++        DirectoryTree {..} -> do+            expression <- getExpression file++            resolvedExpression <-+                Dhall.Import.loadRelativeTo (rootDirectory file) UseSemanticCache expression++            _ <- Dhall.Core.throws (Dhall.TypeCheck.typeOf resolvedExpression)++            let normalizedExpression = Dhall.Core.normalize resolvedExpression++            DirectoryTree.toDirectoryTree allowSeparators path normalizedExpression++        Dhall.Main.Schemas{..} ->+            Dhall.Schemas.schemasCommand Dhall.Schemas.Schemas{ input = file, ..}++        SyntaxTree {..} -> do+            expression <- getExpression file++            if noted then+                Text.Pretty.Simple.pPrintNoColor expression+            else+                let denoted :: Expr Void Import+                    denoted = Dhall.Core.denote expression+                in Text.Pretty.Simple.pPrintNoColor denoted++        Package {..} -> do+            let options = appEndo+                    (maybe mempty (Endo . set Dhall.Package.characterSet) chosenCharacterSet+                    <> packageOptions+                    ) Dhall.Package.defaultOptions+            writePackage options packageFiles+ -- | Entry point for the @dhall@ executable main :: IO () main = do     options <- Options.Applicative.execParser parserInfoOptions-    command options++    Dhall.Main.command options
src/Dhall/Map.hs view
@@ -1,8 +1,11 @@-{-# LANGUAGE CPP                #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# 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 @@ -11,9 +14,16 @@       Map        -- * Construction+    , empty     , singleton     , fromList+    , fromListWithKey+    , fromMap +      -- * Constructing unordered 'Map's+    , unorderedSingleton+    , unorderedFromList+       -- * Sorting     , sort     , isSorted@@ -25,16 +35,21 @@       -- * Deletion/Update     , delete     , filter+    , partition+    , restrictKeys+    , withoutKeys     , mapMaybe        -- * Query     , lookup     , member     , uncons+    , size        -- * Combine     , union     , unionWith+    , outerJoin     , intersection     , intersectionWith     , difference@@ -42,25 +57,33 @@       -- * Traversals     , mapWithKey     , traverseWithKey-    , traverseWithKey_+    , unorderedTraverseWithKey     , unorderedTraverseWithKey_     , foldMapWithKey        -- * Conversions     , toList+    , toAscList     , toMap     , keys+    , keysSet+    , elems     ) where -import Control.Applicative ((<|>))-import Data.Data (Data)-import Data.Foldable (traverse_)-import Data.Semigroup-import Prelude hiding (filter, lookup)+import Control.Applicative        ((<|>))+import Control.DeepSeq            (NFData)+import Data.Data                  (Data)+import GHC.Generics               (Generic)+import Instances.TH.Lift          ()+import Language.Haskell.TH.Syntax (Lift)+import Prelude                    hiding (filter, lookup) -import qualified Data.Functor-import qualified Data.Map+import qualified Data.Foldable.WithIndex    as Foldable.WithIndex+import qualified Data.Functor.WithIndex     as Functor.WithIndex+import qualified Data.List+import qualified Data.Map.Strict import qualified Data.Set+import qualified Data.Traversable.WithIndex as Traversable.WithIndex import qualified GHC.Exts import qualified Prelude @@ -71,44 +94,62 @@     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) [k]-    deriving (Data)+data Map k v = Map (Data.Map.Strict.Map k v) (Keys k)+    deriving (Data, Generic, Lift, NFData) -instance (Eq k, Eq v) => Eq (Map k v) where-  Map m1 ks == Map m2 ks' = m1 == m2 && ks == ks'+data Keys a+    = Sorted+    | Original [a]+    deriving (Data, Generic, Lift, NFData)++instance (Ord k, Eq v) => Eq (Map k v) where+  m1 == m2 =+      Data.Map.Strict.size (toMap m1) == Data.Map.Strict.size (toMap m2)+      && toList m1 == toList m2   {-# INLINABLE (==) #-} +{-|+>>> fromList [("A",1),("B",2)] < fromList [("B",1),("A",0)]+True+-} instance (Ord k, Ord v) => Ord (Map k v) where-  compare (Map mL ksL) (Map mR ksR) = compare mL mR <> compare ksL ksR+  compare m1 m2 = compare (toList m1) (toList m2)+  {-# INLINABLE compare #-}  instance Functor (Map k) where   fmap f (Map m ks) = Map (fmap f m) ks   {-# INLINABLE fmap #-} -instance Foldable (Map k) where-  foldr f z (Map m _) = foldr f z m+instance Ord k => Foldable (Map k) where+  foldr f z (Map m Sorted) = foldr f z m+  foldr f z m              = foldr f z (elems m)   {-# INLINABLE foldr #-} -  foldMap f (Map m _) = foldMap f m-  {-# INLINABLE foldMap #-}+  length m = size m+  {-# INLINABLE length #-} -instance Traversable (Map k) where-  traverse f (Map m ks) = (\m' -> Map m' ks) <$> traverse f m+  null (Map m _) = null m+  {-# INLINABLE null #-}++instance Ord k => Traversable (Map k) where+  traverse f m = traverseWithKey (\_ v -> f v) m   {-# INLINABLE traverse #-} -instance Ord k => Data.Semigroup.Semigroup (Map k v) where+{-|+prop> \x y z -> x <> (y <> z) == (x <> y) <> (z :: Map Int Int)+-}+instance Ord k => Semigroup (Map k v) where     (<>) = union     {-# INLINABLE (<>) #-} +{-|+prop> \x -> x <> mempty == (x :: Map Int Int)+prop> \x -> mempty <> x == (x :: Map Int Int)+-} instance Ord k => Monoid (Map k v) where-    mempty = Map Data.Map.empty []+    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)@@ -122,6 +163,22 @@      toList = Dhall.Map.toList +instance Ord k => Foldable.WithIndex.FoldableWithIndex k (Map k) where+    ifoldMap = foldMapWithKey+    {-# INLINABLE ifoldMap #-}++instance Functor.WithIndex.FunctorWithIndex k (Map k) where+    imap = mapWithKey+    {-# INLINABLE imap #-}++instance Ord k => Traversable.WithIndex.TraversableWithIndex k (Map k) where+    itraverse = traverseWithKey+    {-# INLINABLE itraverse #-}++-- | Create an empty `Map`+empty :: Ord k => Map k v+empty = mempty+ {-| Create a `Map` from a single key-value pair  >>> singleton "A" 1@@ -130,30 +187,52 @@ 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 = pure k+    ks = Original [k] {-# INLINABLE singleton #-}  {-| Create a `Map` from a list of key-value pairs -> fromList empty = mempty->-> fromList (x <|> y) = fromList x <> fromList y- >>> fromList [("B",1),("A",2)]  -- The map preserves order fromList [("B",1),("A",2)] >>> fromList [("A",1),("A",2)]  -- For duplicates, later values take precedence fromList [("A",2)]++Note that this handling of duplicates means that 'fromList' is /not/ a monoid+homomorphism:++>>> fromList [(1, True)] <> fromList [(1, False)]+fromList [(1,True)]+>>> fromList ([(1, True)] <> [(1, False)])+fromList [(1,False)]+ -} fromList :: Ord k => [(k, v)] -> Map k v fromList kvs = Map m ks   where-    m = Data.Map.fromList kvs+    m = Data.Map.Strict.fromList kvs -    ks = nubOrd (map fst kvs)+    ks = Original (nubOrd (map fst kvs)) {-# INLINABLE fromList #-} +{-| Create a `Map` from a list of key-value pairs with a combining function.++>>> fromListWithKey (\k v1 v2 -> k ++ v1 ++ v2) [("B","v1"),("A","v2"),("B","v3")]+fromList [("B","Bv3v1"),("A","v2")]+-}+fromListWithKey :: Ord k => (k -> v -> v -> v) -> [(k, v)] -> Map k v+fromListWithKey f kvs = Map m ks+  where+    m = Data.Map.Strict.fromListWithKey f kvs++    ks = Original (nubOrd (map fst kvs))+{-# INLINABLE fromListWithKey #-}++-- | Create a `Map` from a @"Data.Map.Strict".`Data.Map.Strict.Map`@+fromMap :: Data.Map.Strict.Map k v -> Map k v+fromMap m = Map m Sorted+ {-| Remove duplicates from a  list  >>> nubOrd [1,2,3]@@ -170,6 +249,36 @@         | otherwise             = k : go (Data.Set.insert k set) ks {-# INLINABLE nubOrd #-} +{-| Create a `Map` from a single key-value pair.++    Any further operations on this map will not retain the order of the keys.++>>> unorderedSingleton "A" 1+fromList [("A",1)]+-}+unorderedSingleton :: k -> v -> Map k v+unorderedSingleton k v = Map m Sorted+  where+    m = Data.Map.Strict.singleton k v+{-# INLINABLE unorderedSingleton #-}++{-| Create a `Map` from a list of key-value pairs++    Any further operations on this map will not retain the order of the keys.++>>> unorderedFromList []+fromList []+>>> unorderedFromList [("B",1),("A",2)]  -- The map /doesn't/ preserve order+fromList [("A",2),("B",1)]+>>> unorderedFromList [("A",1),("A",2)]  -- For duplicates, later values take precedence+fromList [("A",2)]+-}+unorderedFromList :: Ord k => [(k, v)] -> Map k v+unorderedFromList kvs = Map m Sorted+  where+    m = Data.Map.Strict.fromList kvs+{-# INLINABLE unorderedFromList #-}+ {-| Sort the keys of a `Map`, forgetting the original ordering  > sort (sort x) = sort x@@ -177,10 +286,8 @@ >>> sort (fromList [("B",1),("A",2)]) fromList [("A",2),("B",1)] -}-sort :: Ord k => Map k v -> Map k v-sort (Map m _) = Map m ks-  where-    ks = Data.Map.keys m+sort :: Map k v -> Map k v+sort (Map m _) = Map m Sorted {-# INLINABLE sort #-}  {-| Check if the keys of a `Map` are already sorted@@ -193,7 +300,8 @@ True -} isSorted :: Eq k => Map k v -> Bool-isSorted (Map m k) = Data.Map.keys m == k+isSorted (Map _ Sorted)        = True+isSorted (Map m (Original ks)) = Data.Map.Strict.keys m == ks -- Or shortcut to False here? {-# INLINABLE isSorted #-}  {-| Insert a key-value pair into a `Map`, overriding any previous value stored@@ -207,12 +315,13 @@ fromList [("C",1),("A",3)] -} insert :: Ord k => k -> v -> Map k v -> Map k v-insert k v (Map m ks) = Map m' ks'+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-    m' = Data.Map.insert k v m+    (mayOldV, m') = Data.Map.Strict.insertLookupWithKey (\_k new _old -> new) k v m -    ks' | elem k ks = ks-        | otherwise = k : ks+    ks' | Just _ <- mayOldV = ks+        | otherwise         = k : ks {-# INLINABLE insert #-}  {-| Insert a key-value pair into a `Map`, using the supplied function to combine@@ -224,12 +333,13 @@ 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 ks) = Map m' ks'+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-    m' = Data.Map.insertWith f k v m+    (mayOldV, m') = Data.Map.Strict.insertLookupWithKey (\_k new old -> f new old) k v m -    ks' | elem k ks = ks-        | otherwise = k : ks+    ks' | Just _ <- mayOldV = ks+        | otherwise         = k : ks {-# INLINABLE insertWith #-}  {-| Delete a key from a `Map` if present, otherwise return the original `Map`@@ -242,9 +352,11 @@ 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' = Prelude.filter (k /=) ks+    ks' = case ks of+        Sorted        -> Sorted+        Original ks'' -> Original (Data.List.delete k ks'') {-# INLINABLE delete #-}  {-| Keep all values that satisfy the given predicate@@ -257,13 +369,52 @@ 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--    set = Data.Map.keysSet m'+    m' = Data.Map.Strict.filter predicate m -    ks' = Prelude.filter (\k -> Data.Set.member k set) ks+    ks' = filterKeys (\k -> Data.Map.Strict.member k m') ks {-# INLINABLE filter #-} +{-| Split the map into values that do and don't satisfy the predicate++>>> partition even (fromList [("C",3),("B",2),("A",1)])+(fromList [("B",2)],fromList [("C",3),("A",1)])+>>> partition odd (fromList [("C",3),("B",2),("A",1)])+(fromList [("C",3),("A",1)],fromList [("B",2)])+-}+partition :: Ord k => (a -> Bool) -> Map k a -> (Map k a, Map k a)+partition predicate (Map m ks) = (Map mpass kpass, Map mfail kfail)+  where+    (mpass, mfail) = Data.Map.Strict.partition predicate m++    (kpass, kfail) = partitionKeys (\k -> Data.Map.Strict.member k mpass) ks+{-# INLINABLE partition #-}++{-| Restrict a 'Map' to only those keys found in a @"Data.Set".'Data.Set.Set'@.++>>> restrictKeys (fromList [("A",1),("B",2)]) (Data.Set.fromList ["A"])+fromList [("A",1)]+-}+restrictKeys :: Ord k => Map k a -> Data.Set.Set k -> Map k a+restrictKeys (Map m ks) s = Map m' ks'+  where+    m' = Data.Map.Strict.restrictKeys m s++    ks' = filterKeys (\k -> Data.Set.member k s) ks+{-# INLINABLE restrictKeys #-}++{-| Remove all keys in a @"Data.Set".'Data.Set.Set'@ from a 'Map'++>>> withoutKeys (fromList [("A",1),("B",2)]) (Data.Set.fromList ["A"])+fromList [("B",2)]+-}+withoutKeys :: Ord k => Map k a -> Data.Set.Set k -> Map k a+withoutKeys (Map m ks) s = Map m' ks'+  where+    m' = Data.Map.Strict.withoutKeys m s++    ks' = filterKeys (\k -> Data.Set.notMember k s) ks+{-# INLINABLE withoutKeys #-}+ {-| Transform all values in a `Map` using the supplied function, deleting the     key if the function returns `Nothing` @@ -273,11 +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--    set = Data.Map.keysSet m'+    m' = Data.Map.Strict.mapMaybe f m -    ks' = Prelude.filter (\k -> Data.Set.member k set) ks+    ks' = filterKeys (\k -> Data.Map.Strict.member k m') ks {-# INLINABLE mapMaybe #-}  {-| Retrieve a key from a `Map`@@ -292,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,@@ -308,8 +457,12 @@ Nothing -} uncons :: Ord k => Map k v -> Maybe (k, v, Map k v)-uncons (Map _ [])     = Nothing-uncons (Map m (k:ks)) = Just (k, m Data.Map.! k, Map (Data.Map.delete k m) ks)+uncons (Map _ (Original []))     = Nothing+uncons (Map m (Original (k:ks))) =+    Just (k, m Data.Map.Strict.! k, Map (Data.Map.Strict.delete k m) (Original ks))+uncons (Map m Sorted)+  | Just ((k, v), m') <- Data.Map.Strict.minViewWithKey m = Just (k, v, Map m' Sorted)+  | otherwise                                      = Nothing {-# INLINABLE uncons #-}  {-| Check if a key belongs to a `Map`@@ -324,9 +477,17 @@ 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 #-} +{-|+>>> size (fromList [("A",1)])+1+-}+size :: Map k v -> Int+size (Map m _) = Data.Map.Strict.size m+{-# INLINABLE size #-}+ {-| Combine two `Map`s, preferring keys from the first `Map`  > union = unionWith (\v _ -> v)@@ -339,11 +500,12 @@ 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--    setL = Data.Map.keysSet mL+    m = Data.Map.Strict.union mL mR -    ks = ksL <|> Prelude.filter (\k -> Data.Set.notMember k setL) ksR+    ks = case (ksL, ksR) of+        (Original l, Original r) -> Original $+            l <|> Prelude.filter (\k -> Data.Map.Strict.notMember k mL) r+        _                        -> Sorted {-# INLINABLE union #-}  {-| Combine two `Map`s using a combining function for colliding keys@@ -356,13 +518,44 @@ 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--    setL = Data.Map.keysSet mL+    m = Data.Map.Strict.unionWith combine mL mR -    ks = ksL <|> Prelude.filter (\k -> Data.Set.notMember k setL) ksR+    ks = case (ksL, ksR) of+        (Original l, Original r) -> Original $+            l <|> Prelude.filter (\k -> Data.Map.Strict.notMember k mL) r+        _                        -> Sorted {-# INLINABLE unionWith #-} +{-| A generalised 'unionWith'.++>>> outerJoin Left Left (\k a b -> Right (k, a, b)) (fromList [("A",1),("B",2)]) (singleton "A" 3)+fromList [("A",Right ("A",1,3)),("B",Left 2)]++This function is much inspired by the "Data.Semialign.Semialign" class.+-}+outerJoin+    :: Ord k+    => (a -> c)+    -> (b -> c)+    -> (k -> a -> b -> c)+    -> Map k a+    -> Map k b+    -> Map k c+outerJoin fa fb fab (Map ma ksA) (Map mb ksB) = Map m ks+  where+    m = Data.Map.Strict.mergeWithKey+            (\k a b -> Just (fab k a b))+            (fmap fa)+            (fmap fb)+            ma+            mb++    ks = case (ksA, ksB) of+        (Original l, Original r) -> Original $+            l <|> Prelude.filter (\k -> Data.Map.Strict.notMember k ma) r+        _                        -> Sorted+{-# INLINABLE outerJoin #-}+ {-| Combine two `Map` on their shared keys, keeping the value from the first     `Map` @@ -374,12 +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 -    setL = Data.Map.keysSet mL-    setR = Data.Map.keysSet mR-    set  = Data.Set.intersection setL setR-    ks   = Prelude.filter (\k -> Data.Set.member k set) ksL+    -- Or forget order unless both maps are ordered?!+    ks = filterKeys (\k -> Data.Map.Strict.member k m) ksL {-# INLINABLE intersection #-}  {-| Combine two `Map`s on their shared keys, using the supplied function to@@ -391,12 +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 -    setL = Data.Map.keysSet mL-    setR = Data.Map.keysSet mR-    set  = Data.Set.intersection setL setR-    ks   = Prelude.filter (\k -> Data.Set.member k set) ksL+    -- Or forget order unless both maps are ordered?!+    ks = filterKeys (\k -> Data.Map.Strict.member k m) ksL {-# INLINABLE intersectionWith #-}  {-| Compute the difference of two `Map`s by subtracting all keys from the@@ -408,11 +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--    setR = Data.Map.keysSet mR+    m = Data.Map.Strict.difference mL mR -    ks = Prelude.filter (\k -> Data.Set.notMember k setR) 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@@ -421,7 +608,8 @@ ("BA",[1,2]) -} foldMapWithKey :: (Monoid m, Ord k) => (k -> a -> m) -> Map k a -> m-foldMapWithKey f m = foldMap (uncurry f) (toList m)+foldMapWithKey f (Map m Sorted) = Data.Map.Strict.foldMapWithKey f m+foldMapWithKey f m              = foldMap (uncurry f) (toList m) {-# INLINABLE foldMapWithKey #-}  {-| Transform the values of a `Map` using their corresponding key@@ -440,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@@ -450,33 +638,33 @@ -} traverseWithKey     :: Ord k => Applicative f => (k -> a -> f b) -> Map k a -> f (Map k b)-traverseWithKey f m =-    fmap fromList (traverse f' (toList m))+traverseWithKey f (Map m Sorted) =+    fmap (\m' -> Map m' Sorted) (Data.Map.Strict.traverseWithKey f m)+traverseWithKey f m@(Map _ ks) =+    flip Map ks . Data.Map.Strict.fromList <$> traverse f' (toList m)   where     f' (k, a) = fmap ((,) k) (f k a) {-# INLINABLE traverseWithKey #-} -{-| Traverse all of the key-value pairs in a `Map`, in their original order-    where the result of the computation can be forgotten.-->>> traverseWithKey_ (\k v -> print (k, v)) (fromList [("B",1),("A",2)])-("B",1)-("A",2)+{-| Same as `traverseWithKey`, except that the order of effects is not+    necessarily the same as the order of the keys -}-traverseWithKey_-    :: Ord k => Applicative f => (k -> a -> f ()) -> Map k a -> f ()-traverseWithKey_ f m = Data.Functor.void (traverseWithKey f m)-{-# INLINABLE traverseWithKey_ #-}+unorderedTraverseWithKey+    :: Ord k => Applicative f => (k -> a -> f b) -> Map k a -> f (Map k b)+unorderedTraverseWithKey f (Map m ks) =+    fmap (\m' -> Map m' ks) (Data.Map.Strict.traverseWithKey f m)+{-# INLINABLE unorderedTraverseWithKey #-} -{-| Travese all of the key-value pairs in a 'Map', not preserving their+{-| Traverse all of the key-value pairs in a 'Map', not preserving their     original order, where the result of the computation can be forgotten. -    Note that this is an optimisation over 'traverseWithKey_' since we do-    not care in what order we traverse the pairs.+    Note that this is a strict traversal, fully traversing the map even+    when the Applicative is lazy in the remaining elements. -} unorderedTraverseWithKey_     :: Ord k => Applicative f => (k -> a -> f ()) -> Map k a -> f ()-unorderedTraverseWithKey_ f = Data.Functor.void . traverse_ (uncurry f) . toList+unorderedTraverseWithKey_ f (Map m _) =+    Data.Map.Strict.foldlWithKey' (\acc k v -> acc *> f k v) (pure ()) m {-# INLINABLE unorderedTraverseWithKey_ #-}  {-| Convert a `Map` to a list of key-value pairs in the original order of keys@@ -485,15 +673,22 @@ [("B",1),("A",2)] -} toList :: Ord k => Map k v -> [(k, v)]-toList (Map m 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 @"Dhall.Map".`Map`@ to a @"Data.Map".`Data.Map.Map`@+{-| Convert a `Map` to a list of key-value pairs in ascending order of keys+-}+toAscList :: Map k v -> [(k, v)]+toAscList (Map m _) = Data.Map.Strict.toAscList m+{-# INLINABLE toAscList #-} +{-| Convert a @"Dhall.Map".`Map`@ to a @"Data.Map.Strict".`Data.Map.Strict.Map`@+ >>> toMap (fromList [("B",1),("A",2)]) -- Order is lost upon conversion fromList [("A",2),("B",1)] -}-toMap :: Map k v -> Data.Map.Map k v+toMap :: Map k v -> Data.Map.Strict.Map k v toMap (Map m _) = m {-# INLINABLE toMap #-} @@ -503,5 +698,45 @@ ["B","A"] -} keys :: Map k v -> [k]-keys (Map _ ks) = ks+keys (Map m Sorted)        = Data.Map.Strict.keys m+keys (Map _ (Original ks)) = ks {-# INLINABLE keys #-}++{-| Return the values from a `Map` in their original order.++>>> elems (fromList [("B",1),("A",2)])+[1,2]+-}+elems :: Ord k => Map k v -> [v]+elems (Map m Sorted)        = Data.Map.Strict.elems m+elems (Map m (Original ks)) = fmap (\k -> m Data.Map.Strict.! k) ks+{-# INLINABLE elems #-}++{-| Return the @"Data.Set".'Data.Set.Set'@ of the keys++>>> keysSet (fromList [("B",1),("A",2)])+fromList ["A","B"]+-}+keysSet :: Map k v -> Data.Set.Set k+keysSet (Map m _) = Data.Map.Strict.keysSet m+{-# INLINABLE keysSet #-}++filterKeys :: (a -> Bool) -> Keys a -> Keys a+filterKeys _ Sorted        = Sorted+filterKeys f (Original ks) = Original (Prelude.filter f ks)+{-# INLINABLE filterKeys #-}++partitionKeys :: (a -> Bool) -> Keys a -> (Keys a, Keys a)+partitionKeys _ Sorted        = (Sorted, Sorted)+partitionKeys f (Original ks) =+    let (kpass, kfail) = Data.List.partition f ks+    in (Original kpass, Original kfail)+{-# INLINABLE partitionKeys #-}++{- $setup+>>> import Test.QuickCheck (Arbitrary(..), oneof)+>>> :{+  instance (Ord k, Arbitrary k, Arbitrary v) => Arbitrary (Map k v) where+    arbitrary = oneof [fromList <$> arbitrary, unorderedFromList <$> arbitrary]+:}+-}
+ src/Dhall/Marshal/Decode.hs view
@@ -0,0 +1,1712 @@+{-# LANGUAGE ApplicativeDo              #-}+{-# LANGUAGE CPP                        #-}+{-# LANGUAGE ConstraintKinds            #-}+{-# LANGUAGE DefaultSignatures          #-}+{-# LANGUAGE DeriveFunctor              #-}+{-# LANGUAGE DerivingStrategies         #-}+{-# LANGUAGE FlexibleContexts           #-}+{-# LANGUAGE FlexibleInstances          #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses      #-}+{-# LANGUAGE NamedFieldPuns             #-}+{-# LANGUAGE OverloadedStrings          #-}+{-# LANGUAGE PolyKinds                  #-}+{-# LANGUAGE RankNTypes                 #-}+{-# LANGUAGE RecordWildCards            #-}+{-# LANGUAGE ScopedTypeVariables        #-}+{-# LANGUAGE StandaloneDeriving         #-}+{-# LANGUAGE TypeApplications           #-}+{-# LANGUAGE TypeFamilies               #-}+{-# LANGUAGE TypeOperators              #-}+{-# LANGUAGE UndecidableInstances       #-}+{-# LANGUAGE ViewPatterns               #-}++{-| Please read the "Dhall.Tutorial" module, which contains a tutorial explaining+    how to use the language, the compiler, and this library+-}++module Dhall.Marshal.Decode+    ( -- * General+      Decoder (..)+    , FromDhall(..)+    , Interpret+    , auto++      -- * Building decoders+      -- ** Simple decoders+    , bool+    , unit+    , void+      -- ** Numbers+    , natural+    , word+    , word8+    , word16+    , word32+    , word64+    , integer+    , int+    , int8+    , int16+    , int32+    , int64+    , scientific+    , double+      -- ** Bytes+    , lazyBytes+    , strictBytes+    , shortBytes+      -- ** Textual+    , string+    , lazyText+    , strictText+    , shortText+      -- ** Time+    , timeOfDay+    , day+    , timeZone+    , localTime+    , zonedTime+    , utcTime+    , dayOfWeek+      -- ** Containers+    , maybe+    , pair+    , sequence+    , list+    , vector+    , setFromDistinctList+    , setIgnoringDuplicates+    , hashSetFromDistinctList+    , hashSetIgnoringDuplicates+    , Dhall.Marshal.Decode.map+    , hashMap+    , pairFromMapEntry+      -- ** Functions+    , function+    , functionWith+      -- ** Records+    , RecordDecoder(..)+    , record+    , field+      -- ** Unions+    , UnionDecoder(..)+    , union+    , constructor++      -- * Generic decoding+    , GenericFromDhall(..)+    , GenericFromDhallUnion(..)+    , genericAuto+    , genericAutoWith+    , genericAutoWithInputNormalizer++    -- * Decoding errors+    , DhallErrors(..)+    , showDhallErrors+    , InvalidDecoder(..)+    -- ** Extraction errors+    , ExtractErrors+    , ExtractError(..)+    , Extractor+    , typeError+    , extractError+    , MonadicExtractor+    , toMonadic+    , fromMonadic+    -- ** Typing errors+    , ExpectedTypeErrors+    , ExpectedTypeError(..)+    , Expector++    -- * Miscellaneous+    , InputNormalizer(..)+    , defaultInputNormalizer+    , InterpretOptions(..)+    , SingletonConstructors(..)+    , defaultInterpretOptions+    , Result++    -- * Re-exports+    , Natural+    , Seq+    , Text+    , Vector+    , Generic+    ) where+++import Control.Applicative              (empty, liftA2)+import Control.Exception                (Exception)+import Control.Monad                    (guard)+import Control.Monad.Trans.State.Strict+import Data.Coerce                      (coerce)+import Data.Either.Validation+    ( Validation (..)+    , eitherToValidation+    , validationToEither+    )+import Data.Functor.Contravariant+    ( Equivalence (..)+    , Op (..)+    , Predicate (..)+    )+import Data.Functor.Identity            (Identity (..))+import Data.Hashable                    (Hashable)+import Data.List.NonEmpty               (NonEmpty (..))+import Data.Typeable                    (Proxy (..), Typeable)+import Dhall.Parser                     (Src (..))+import Dhall.Syntax+    ( Chunks (..)+    , DhallDouble (..)+    , Expr (..)+    , FieldSelection (..)+    , FunctionBinding (..)+    , Var (..)+    )+import GHC.Generics+import Prelude                          hiding (maybe, sequence)+import Prettyprinter                    (Pretty)++import qualified Control.Applicative+import qualified Data.ByteString+import qualified Data.ByteString.Lazy+import qualified Data.ByteString.Short+import qualified Data.Foldable+import qualified Data.Functor.Compose+import qualified Data.Functor.Product+import qualified Data.HashMap.Strict   as HashMap+import qualified Data.HashSet+import qualified Data.List             as List+import qualified Data.List.NonEmpty+import qualified Data.Map+import qualified Data.Maybe+import qualified Data.Scientific+import qualified Data.Sequence+import qualified Data.Set+import qualified Data.Text+import qualified Data.Text.Lazy+import qualified Data.Text.Short+import qualified Data.Time             as Time+import qualified Data.Vector+import qualified Dhall.Core            as Core+import qualified Dhall.Map+import qualified Dhall.Util++import Dhall.Marshal.Encode+import Dhall.Marshal.Internal++-- $setup+-- >>> import Dhall (input)++{-| A @(Decoder a)@ represents a way to marshal a value of type @\'a\'@ from Dhall+    into Haskell.++    You can produce `Decoder`s either explicitly:++> example :: Decoder (Vector Text)+> example = vector text++    ... or implicitly using `auto`:++> example :: Decoder (Vector Text)+> example = auto++    You can consume `Decoder`s using the `Dhall.input` function:++> input :: Decoder a -> Text -> IO a+-}+data Decoder a = Decoder+    { extract  :: Expr Src Void -> Extractor Src Void a+    -- ^ Extracts Haskell value from the Dhall expression+    , expected :: Expector (Expr Src Void)+    -- ^ Dhall type of the Haskell value+    }+    deriving (Functor)++{-| Any value that implements `FromDhall` can be automatically decoded based on+    the inferred return type of `Dhall.input`.++>>> input auto "[1, 2, 3]" :: IO (Vector Natural)+[1,2,3]+>>> input auto "toMap { a = False, b = True }" :: IO (Map Text Bool)+fromList [("a",False),("b",True)]++    This class auto-generates a default implementation for types that+    implement `Generic`.  This does not auto-generate an instance for recursive+    types.++    The default instance can be tweaked using 'genericAutoWith'/'genericAutoWithInputNormalizer'+    and custom 'InterpretOptions', or using+    [DerivingVia](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#extension-DerivingVia)+    and 'Dhall.Deriving.Codec' from "Dhall.Deriving".+-}+class FromDhall a where+    autoWith :: InputNormalizer -> Decoder a+    default autoWith+        :: (Generic a, GenericFromDhall a (Rep a)) => InputNormalizer -> Decoder a+    autoWith _ = genericAuto++-- | A compatibility alias for `FromDhall`.+type Interpret = FromDhall+{-# DEPRECATED Interpret "Use FromDhall instead" #-}++{-| Use the default input normalizer for interpreting an input.++> auto = autoWith defaultInputNormalizer+-}+auto :: FromDhall a => Decoder a+auto = autoWith defaultInputNormalizer++++instance FromDhall Void where+    autoWith _ = void++instance FromDhall () where+    autoWith _ = unit++instance FromDhall Bool where+    autoWith _ = bool++instance FromDhall Natural where+    autoWith _ = natural++instance FromDhall Word where+    autoWith _ = word++instance FromDhall Word8 where+    autoWith _ = word8++instance FromDhall Word16 where+    autoWith _ = word16++instance FromDhall Word32 where+    autoWith _ = word32++instance FromDhall Word64 where+    autoWith _ = word64++instance FromDhall Integer where+    autoWith _ = integer++instance FromDhall Int where+    autoWith _ = int++instance FromDhall Int8 where+    autoWith _ = int8++instance FromDhall Int16 where+    autoWith _ = int16++instance FromDhall Int32 where+    autoWith _ = int32++instance FromDhall Int64 where+    autoWith _ = int64++instance FromDhall Scientific where+    autoWith _ = scientific++instance FromDhall Double where+    autoWith _ = double++instance FromDhall Data.ByteString.Short.ShortByteString where+    autoWith _ = shortBytes++instance FromDhall Data.ByteString.Lazy.ByteString where+    autoWith _ = lazyBytes++instance FromDhall Data.ByteString.ByteString where+    autoWith _ = strictBytes++instance {-# OVERLAPS #-} FromDhall [Char] where+    autoWith _ = string++instance FromDhall Data.Text.Short.ShortText where+    autoWith _ = shortText++instance FromDhall Data.Text.Lazy.Text where+    autoWith _ = lazyText++instance FromDhall Text where+    autoWith _ = strictText++instance FromDhall a => FromDhall (Identity a) where+    autoWith opts = Identity <$> autoWith opts++instance FromDhall a => FromDhall (Maybe a) where+    autoWith opts = maybe (autoWith opts)++instance FromDhall a => FromDhall (Seq a) where+    autoWith opts = sequence (autoWith opts)++instance FromDhall a => FromDhall [a] where+    autoWith opts = list (autoWith opts)++instance FromDhall a => FromDhall (Vector a) where+    autoWith opts = vector (autoWith opts)++instance FromDhall Time.TimeOfDay where+    autoWith _ = timeOfDay++instance FromDhall Time.Day where+    autoWith _ = day++instance FromDhall Time.TimeZone where+    autoWith _ = timeZone++instance FromDhall Time.LocalTime where+    autoWith _ = localTime++instance FromDhall Time.ZonedTime where+    autoWith _ = zonedTime++instance FromDhall Time.UTCTime where+    autoWith _ = utcTime++instance FromDhall Time.DayOfWeek where+    autoWith _ = dayOfWeek++{-| Note that this instance will throw errors in the presence of duplicates in+    the list. To ignore duplicates, use `setIgnoringDuplicates`.+-}+instance (FromDhall a, Ord a, Show a) => FromDhall (Data.Set.Set a) where+    autoWith opts = setFromDistinctList (autoWith opts)++{-| Note that this instance will throw errors in the presence of duplicates in+    the list. To ignore duplicates, use `hashSetIgnoringDuplicates`.+-}+instance (FromDhall a, Hashable a, Ord a, Show a) => FromDhall (Data.HashSet.HashSet a) where+    autoWith inputNormalizer = hashSetFromDistinctList (autoWith inputNormalizer)++instance (Ord k, FromDhall k, FromDhall v) => FromDhall (Map k v) where+    autoWith inputNormalizer = Dhall.Marshal.Decode.map (autoWith inputNormalizer) (autoWith inputNormalizer)++instance (Eq k, Hashable k, FromDhall k, FromDhall v) => FromDhall (HashMap k v) where+    autoWith inputNormalizer = Dhall.Marshal.Decode.hashMap (autoWith inputNormalizer) (autoWith inputNormalizer)++instance (ToDhall a, FromDhall b) => FromDhall (a -> b) where+    autoWith inputNormalizer =+        functionWith inputNormalizer (injectWith inputNormalizer) (autoWith inputNormalizer)++instance (FromDhall a, FromDhall b) => FromDhall (a, b)++instance FromDhall (f (Result f)) => FromDhall (Result f) where+    autoWith inputNormalizer = Decoder {..}+      where+        extract (App _ expr) =+            fmap Result (Dhall.Marshal.Decode.extract (autoWith inputNormalizer) expr)+        extract expr = typeError expected expr++        expected = pure "result"++deriving newtype instance (ToDhall x) => FromDhall (Predicate x)++deriving newtype instance (ToDhall x) => FromDhall (Equivalence x)++deriving newtype instance (FromDhall b, ToDhall x) => FromDhall (Op b x)++-- | You can use this instance to marshal recursive types from Dhall to Haskell.+--+-- Here is an example use of this instance:+--+-- > {-# LANGUAGE DeriveAnyClass     #-}+-- > {-# LANGUAGE DeriveFoldable     #-}+-- > {-# LANGUAGE DeriveFunctor      #-}+-- > {-# LANGUAGE DeriveTraversable  #-}+-- > {-# LANGUAGE DeriveGeneric      #-}+-- > {-# LANGUAGE KindSignatures     #-}+-- > {-# LANGUAGE QuasiQuotes        #-}+-- > {-# LANGUAGE StandaloneDeriving #-}+-- > {-# LANGUAGE TypeFamilies       #-}+-- > {-# LANGUAGE TemplateHaskell    #-}+-- >+-- > import Data.Fix (Fix(..))+-- > import Data.Text (Text)+-- > import Dhall (FromDhall)+-- > import GHC.Generics (Generic)+-- > import Numeric.Natural (Natural)+-- >+-- > import qualified Data.Fix                 as Fix+-- > import qualified Data.Functor.Foldable    as Foldable+-- > import qualified Data.Functor.Foldable.TH as TH+-- > import qualified Dhall+-- > import qualified NeatInterpolation+-- >+-- > data Expr+-- >     = Lit Natural+-- >     | Add Expr Expr+-- >     | Mul Expr Expr+-- >     deriving (Show)+-- >+-- > TH.makeBaseFunctor ''Expr+-- >+-- > deriving instance Generic (ExprF a)+-- > deriving instance FromDhall a => FromDhall (ExprF a)+-- >+-- > example :: Text+-- > example = [NeatInterpolation.text|+-- >     \(Expr : Type)+-- > ->  let ExprF =+-- >           < LitF :+-- >               Natural+-- >           | AddF :+-- >               { _1 : Expr, _2 : Expr }+-- >           | MulF :+-- >               { _1 : Expr, _2 : Expr }+-- >           >+-- >+-- >     in      \(Fix : ExprF -> Expr)+-- >         ->  let Lit = \(x : Natural) -> Fix (ExprF.LitF x)+-- >+-- >             let Add =+-- >                       \(x : Expr)+-- >                   ->  \(y : Expr)+-- >                   ->  Fix (ExprF.AddF { _1 = x, _2 = y })+-- >+-- >             let Mul =+-- >                       \(x : Expr)+-- >                   ->  \(y : Expr)+-- >                   ->  Fix (ExprF.MulF { _1 = x, _2 = y })+-- >+-- >             in  Add (Mul (Lit 3) (Lit 7)) (Add (Lit 1) (Lit 2))+-- > |]+-- >+-- > convert :: Fix ExprF -> Expr+-- > convert = Fix.foldFix Foldable.embed+-- >+-- > main :: IO ()+-- > main = do+-- >     x <- Dhall.input Dhall.auto example :: IO (Fix ExprF)+-- >+-- >     print (convert x :: Expr)+instance (Functor f, FromDhall (f (Result f))) => FromDhall (Fix f) where+    autoWith inputNormalizer = Decoder {..}+      where+        extract expr0 = extract0 expr0+          where+            die = typeError expected expr0++            extract0 (Lam _ (FunctionBinding { functionBindingVariable = x }) expr) =+                extract1 (rename x "result" expr)+            extract0  _             = die++            extract1 (Lam _ (FunctionBinding { functionBindingVariable = y }) expr) =+                extract2 (rename y "Make" expr)+            extract1  _             = die++            extract2 expr = fmap resultToFix (Dhall.Marshal.Decode.extract (autoWith inputNormalizer) expr)++            rename a b expr+                | a /= b    = Core.subst (V a 0) (Var (V b 0)) (Core.shift 1 (V b 0) expr)+                | otherwise = expr++        expected = (\x -> Pi mempty "result" (Const Core.Type) (Pi mempty "Make" (Pi mempty "_" x "result") "result"))+            <$> Dhall.Marshal.Decode.expected (autoWith inputNormalizer :: Decoder (f (Result f)))++resultToFix :: Functor f => Result f -> Fix f+resultToFix (Result x) = Fix (fmap resultToFix x)++++{-| This is the underlying class that powers the `FromDhall` class's support+    for automatically deriving a generic implementation.+-}+class GenericFromDhall t f where+    genericAutoWithNormalizer :: Proxy t -> InputNormalizer -> InterpretOptions -> State Int (Decoder (f a))++instance GenericFromDhall t f => GenericFromDhall t (M1 D d f) where+    genericAutoWithNormalizer p inputNormalizer options = do+        res <- genericAutoWithNormalizer p inputNormalizer options+        pure (fmap M1 res)++instance GenericFromDhall t V1 where+    genericAutoWithNormalizer _ _ _ = pure Decoder {..}+      where+        extract expr = typeError expected expr++        expected = pure $ Union mempty++instance GenericFromDhallUnion t (f :+: g) => GenericFromDhall t (f :+: g) where+  genericAutoWithNormalizer p inputNormalizer options =+    pure (union (genericUnionAutoWithNormalizer p inputNormalizer options))++instance GenericFromDhall t f => GenericFromDhall t (M1 C c f) where+    genericAutoWithNormalizer p inputNormalizer options = do+        res <- genericAutoWithNormalizer p inputNormalizer options+        pure (fmap M1 res)++instance GenericFromDhall t U1 where+    genericAutoWithNormalizer _ _ _ = pure (Decoder {..})+      where+        extract _ = pure U1++        expected = pure expected'++        expected' = Record (Dhall.Map.fromList [])++instance (GenericFromDhall t (f :*: g), GenericFromDhall t (h :*: i)) => GenericFromDhall t ((f :*: g) :*: (h :*: i)) where+    genericAutoWithNormalizer p inputNormalizer options = do+        Decoder extractL expectedL <- genericAutoWithNormalizer p inputNormalizer options+        Decoder extractR expectedR <- genericAutoWithNormalizer p inputNormalizer options++        let ktsL = unsafeExpectRecord "genericAutoWithNormalizer (:*:)" <$> expectedL+        let ktsR = unsafeExpectRecord "genericAutoWithNormalizer (:*:)" <$> expectedR++        let expected = Record <$> (Dhall.Map.union <$> ktsL <*> ktsR)++        let extract expression =+                liftA2 (:*:) (extractL expression) (extractR expression)++        return (Decoder {..})++instance (GenericFromDhall t (f :*: g), Selector s, FromDhall a) => GenericFromDhall t ((f :*: g) :*: M1 S s (K1 i a)) where+    genericAutoWithNormalizer p inputNormalizer options@InterpretOptions{..} = do+        let nR :: M1 S s (K1 i a) r+            nR = undefined++        nameR <- fmap fieldModifier (getSelName nR)++        Decoder extractL expectedL <- genericAutoWithNormalizer p inputNormalizer options++        let Decoder extractR expectedR = autoWith inputNormalizer++        let ktsL = unsafeExpectRecord "genericAutoWithNormalizer (:*:)" <$> expectedL++        let expected = Record <$> (Dhall.Map.insert nameR . Core.makeRecordField <$> expectedR <*> ktsL)++        let extract expression = do+                let die = typeError expected expression++                case expression of+                    RecordLit kvs ->+                        case Core.recordFieldValue <$> Dhall.Map.lookup nameR kvs of+                            Just expressionR ->+                                liftA2 (:*:)+                                    (extractL expression)+                                    (fmap (M1 . K1) (extractR expressionR))+                            _ -> die+                    _ -> die++        return (Decoder {..})++instance (Selector s, FromDhall a, GenericFromDhall t (f :*: g)) => GenericFromDhall t (M1 S s (K1 i a) :*: (f :*: g)) where+    genericAutoWithNormalizer p inputNormalizer options@InterpretOptions{..} = do+        let nL :: M1 S s (K1 i a) r+            nL = undefined++        nameL <- fmap fieldModifier (getSelName nL)++        let Decoder extractL expectedL = autoWith inputNormalizer++        Decoder extractR expectedR <- genericAutoWithNormalizer p inputNormalizer options++        let ktsR = unsafeExpectRecord "genericAutoWithNormalizer (:*:)" <$> expectedR++        let expected = Record <$> (Dhall.Map.insert nameL . Core.makeRecordField <$> expectedL <*> ktsR)++        let extract expression = do+                let die = typeError expected expression++                case expression of+                    RecordLit kvs ->+                        case Core.recordFieldValue <$> Dhall.Map.lookup nameL kvs of+                            Just expressionL ->+                                liftA2 (:*:)+                                    (fmap (M1 . K1) (extractL expressionL))+                                    (extractR expression)+                            _ -> die+                    _ -> die++        return (Decoder {..})++instance {-# OVERLAPPING #-} GenericFromDhall a1 (M1 S s1 (K1 i1 a1) :*: M1 S s2 (K1 i2 a2)) where+    genericAutoWithNormalizer _ _ _ = pure $ Decoder+        { extract = \_ -> Failure $ DhallErrors $ pure $ ExpectedTypeError RecursiveTypeError+        , expected = Failure $ DhallErrors $ pure RecursiveTypeError+        }++instance {-# OVERLAPPING #-} GenericFromDhall a2 (M1 S s1 (K1 i1 a1) :*: M1 S s2 (K1 i2 a2)) where+    genericAutoWithNormalizer _ _ _ = pure $ Decoder+        { extract = \_ -> Failure $ DhallErrors $ pure $ ExpectedTypeError RecursiveTypeError+        , expected = Failure $ DhallErrors $ pure RecursiveTypeError+        }++instance {-# OVERLAPPABLE #-} (Selector s1, Selector s2, FromDhall a1, FromDhall a2) => GenericFromDhall t (M1 S s1 (K1 i1 a1) :*: M1 S s2 (K1 i2 a2)) where+    genericAutoWithNormalizer _ inputNormalizer InterpretOptions{..} = do+        let nL :: M1 S s1 (K1 i1 a1) r+            nL = undefined++        let nR :: M1 S s2 (K1 i2 a2) r+            nR = undefined++        nameL <- fmap fieldModifier (getSelName nL)+        nameR <- fmap fieldModifier (getSelName nR)++        let Decoder extractL expectedL = autoWith inputNormalizer+        let Decoder extractR expectedR = autoWith inputNormalizer++        let expected = do+                l <- Core.makeRecordField <$> expectedL+                r <- Core.makeRecordField <$> expectedR+                pure $ Record+                    (Dhall.Map.fromList+                        [ (nameL, l)+                        , (nameR, r)+                        ]+                    )++        let extract expression = do+                let die = typeError expected expression++                case expression of+                    RecordLit kvs ->+                        case liftA2 (,) (Dhall.Map.lookup nameL kvs) (Dhall.Map.lookup nameR kvs) of+                            Just (expressionL, expressionR) ->+                                liftA2 (:*:)+                                    (fmap (M1 . K1) (extractL $ Core.recordFieldValue expressionL))+                                    (fmap (M1 . K1) (extractR $ Core.recordFieldValue expressionR))+                            Nothing -> die+                    _ -> die++        return (Decoder {..})++instance {-# OVERLAPPING #-} GenericFromDhall a (M1 S s (K1 i a)) where+    genericAutoWithNormalizer _ _ _ = pure $ Decoder+        { extract = \_ -> Failure $ DhallErrors $ pure $ ExpectedTypeError RecursiveTypeError+        , expected = Failure $ DhallErrors $ pure RecursiveTypeError+        }++instance {-# OVERLAPPABLE #-} (Selector s, FromDhall a) => GenericFromDhall t (M1 S s (K1 i a)) where+    genericAutoWithNormalizer _ inputNormalizer InterpretOptions{..} = do+        let n :: M1 S s (K1 i a) r+            n = undefined++        name <- fmap fieldModifier (getSelName n)++        let Decoder { extract = extract', expected = expected'} = autoWith inputNormalizer++        let expected =+                case singletonConstructors of+                    Bare ->+                        expected'+                    Smart | selName n == "" ->+                        expected'+                    _ ->+                        Record . Dhall.Map.singleton name . Core.makeRecordField <$> expected'++        let extract0 expression = fmap (M1 . K1) (extract' expression)++        let extract1 expression = do+                let die = typeError expected expression++                case expression of+                    RecordLit kvs ->+                        case Core.recordFieldValue <$> Dhall.Map.lookup name kvs of+                            Just subExpression ->+                                fmap (M1 . K1) (extract' subExpression)+                            Nothing ->+                                die+                    _ -> die++        let extract =+                case singletonConstructors of+                    Bare                    -> extract0+                    Smart | selName n == "" -> extract0+                    _                       -> extract1++        return (Decoder {..})++{-| `genericAuto` is the default implementation for `auto` if you derive+    `FromDhall`.  The difference is that you can use `genericAuto` without+    having to explicitly provide a `FromDhall` instance for a type as long as+    the type derives `Generic`.+-}+genericAuto :: (Generic a, GenericFromDhall a (Rep a)) => Decoder a+genericAuto = genericAutoWith defaultInterpretOptions++{-| `genericAutoWith` is a configurable version of `genericAuto`.+-}+genericAutoWith :: (Generic a, GenericFromDhall a (Rep a)) => InterpretOptions -> Decoder a+genericAutoWith options = genericAutoWithInputNormalizer options defaultInputNormalizer++{-| `genericAutoWithInputNormalizer` is like `genericAutoWith`, but instead of+    using the `defaultInputNormalizer` it expects an custom `InputNormalizer`.+-}+genericAutoWithInputNormalizer :: (Generic a, GenericFromDhall a (Rep a)) => InterpretOptions -> InputNormalizer -> Decoder a+genericAutoWithInputNormalizer options inputNormalizer = withProxy (\p -> fmap to (evalState (genericAutoWithNormalizer p inputNormalizer options) 1))+    where+        withProxy :: (Proxy a -> Decoder a) -> Decoder a+        withProxy f = f Proxy++extractUnionConstructor+    :: Expr s a -> Maybe (Text, Expr s a, Dhall.Map.Map Text (Maybe (Expr s a)))+extractUnionConstructor (App (Field (Union kts) (Core.fieldSelectionLabel -> fld)) e) =+  return (fld, e, Dhall.Map.delete fld kts)+extractUnionConstructor (Field (Union kts) (Core.fieldSelectionLabel -> fld)) =+  return (fld, RecordLit mempty, Dhall.Map.delete fld kts)+extractUnionConstructor _ =+  empty++{-| This is the underlying class that powers the `FromDhall` class's support+    for automatically deriving a generic implementation for a union type.+-}+class GenericFromDhallUnion t f where+    genericUnionAutoWithNormalizer :: Proxy t -> InputNormalizer -> InterpretOptions -> UnionDecoder (f a)++instance (GenericFromDhallUnion t f1, GenericFromDhallUnion t f2) => GenericFromDhallUnion t (f1 :+: f2) where+  genericUnionAutoWithNormalizer p inputNormalizer options =+    (<>)+      (L1 <$> genericUnionAutoWithNormalizer p inputNormalizer options)+      (R1 <$> genericUnionAutoWithNormalizer p inputNormalizer options)++instance (Constructor c1, GenericFromDhall t f1) => GenericFromDhallUnion t (M1 C c1 f1) where+  genericUnionAutoWithNormalizer p inputNormalizer options@(InterpretOptions {..}) =+    constructor name (evalState (genericAutoWithNormalizer p inputNormalizer options) 1)+    where+      n :: M1 C c1 f1 a+      n = undefined++      name = constructorModifier (Data.Text.pack (conName n))++++{-| Decode a `Prelude.Bool`.++>>> input bool "True"+True+-}+bool :: Decoder Bool+bool = Decoder {..}+  where+    extract (BoolLit b) = pure b+    extract expr        = typeError expected expr++    expected = pure Bool++{-| Decode a `Prelude.Natural`.++>>> input natural "42"+42+-}+natural :: Decoder Natural+natural = Decoder {..}+  where+    extract (NaturalLit n) = pure n+    extract  expr          = typeError expected expr++    expected = pure Natural++{-| Decode an `Prelude.Integer`.++>>> input integer "+42"+42+-}+integer :: Decoder Integer+integer = Decoder {..}+  where+    extract (IntegerLit n) = pure n+    extract  expr          = typeError expected expr++    expected = pure Integer++wordHelper :: forall a . (Bounded a, Integral a) => Text -> Decoder a+wordHelper name = Decoder {..}+  where+    extract (NaturalLit n)+        | toInteger n <= toInteger (maxBound @a) =+            pure (fromIntegral n)+        | otherwise =+            extractError ("Decoded " <> name <> " is out of bounds: " <> Data.Text.pack (show n))+    extract expr =+        typeError expected expr++    expected = pure Natural++{-| Decode a `Word` from a Dhall @Natural@.++>>> input word "42"+42+-}+word :: Decoder Word+word = wordHelper "Word"++{-| Decode a `Word8` from a Dhall @Natural@.++>>> input word8 "42"+42+-}+word8 :: Decoder Word8+word8 = wordHelper "Word8"++{-| Decode a `Word16` from a Dhall @Natural@.++>>> input word16 "42"+42+-}+word16 :: Decoder Word16+word16 = wordHelper "Word16"++{-| Decode a `Word32` from a Dhall @Natural@.++>>> input word32 "42"+42+-}+word32 :: Decoder Word32+word32 = wordHelper "Word32"++{-| Decode a `Word64` from a Dhall @Natural@.++>>> input word64 "42"+42+-}+word64 :: Decoder Word64+word64 = wordHelper "Word64"++intHelper :: forall a . (Bounded a, Integral a) => Text -> Decoder a+intHelper name = Decoder {..}+  where+    extract (IntegerLit n)+        | toInteger (minBound @a) <= n && n <= toInteger (maxBound @a) =+            pure (fromIntegral n)+        | otherwise =+            extractError ("Decoded " <> name <> " is out of bounds: " <> Data.Text.pack (show n))+    extract expr =+        typeError expected expr++    expected = pure Integer++{-| Decode an `Int` from a Dhall @Integer@.++>>> input int "-42"+-42+-}+int :: Decoder Int+int = intHelper "Int"++{-| Decode an `Int8` from a Dhall @Integer@.++>>> input int8 "-42"+-42+-}+int8 :: Decoder Int8+int8 = intHelper "Int8"++{-| Decode an `Int16` from a Dhall @Integer@.++>>> input int16 "-42"+-42+-}+int16 :: Decoder Int16+int16 = intHelper "Int16"++{-| Decode an `Int32` from a Dhall @Integer@.++>>> input int32 "-42"+-42+-}+int32 :: Decoder Int32+int32 = intHelper "Int32"++{-| Decode an `Int64` from a Dhall @Integer@.++>>> input int64 "-42"+-42+-}+int64 :: Decoder Int64+int64 = intHelper "Int64"++{-| Decode a `Scientific`.++>>> input scientific "1e100"+1.0e100+-}+scientific :: Decoder Scientific+scientific = fmap Data.Scientific.fromFloatDigits double++{-| Decode a `Prelude.Double`.++>>> input double "42.0"+42.0+-}+double :: Decoder Double+double = Decoder {..}+  where+    extract (DoubleLit (DhallDouble n)) = pure n+    extract  expr                       = typeError expected expr++    expected = pure Double++{-| Decode a `Data.ByteString.Short.ShortByteString`++>>> input shortBytes "0x\"00FF\""+"\NUL\255"+-}+shortBytes :: Decoder Data.ByteString.Short.ShortByteString+shortBytes = fmap Data.ByteString.Short.toShort strictBytes++{-| Decode a lazy `Data.ByteString.Lazy.ByteString`.++>>> input lazyBytes "0x\"00FF\""+"\NUL\255"+-}+lazyBytes :: Decoder Data.ByteString.Lazy.ByteString+lazyBytes = fmap Data.ByteString.Lazy.fromStrict strictBytes++{-| Decode a strict `Data.ByteString.ByteString`++>>> input strictBytes "0x\"00FF\""+"\NUL\255"+-}+strictBytes :: Decoder Data.ByteString.ByteString+strictBytes = Decoder {..}+  where+    extract (BytesLit b) = pure b+    extract  expr        = typeError expected expr++    expected = pure Bytes++{-| Decode `Data.Text.Short.ShortText`.++>>> input shortText "\"Test\""+"Test"+-}+shortText :: Decoder Data.Text.Short.ShortText+shortText = fmap Data.Text.Short.fromText strictText++{-| Decode lazy `Data.Text.Lazy.Text`.++>>> input lazyText "\"Test\""+"Test"+-}+lazyText :: Decoder Data.Text.Lazy.Text+lazyText = fmap Data.Text.Lazy.fromStrict strictText++{-| Decode strict `Data.Text.Text`.++>>> input strictText "\"Test\""+"Test"+-}+strictText :: Decoder Text+strictText = Decoder {..}+  where+    extract (TextLit (Chunks [] t)) = pure t+    extract  expr                   = typeError expected expr++    expected = pure Text++{-| Decode `Time.TimeOfDay`++>>> input timeOfDay "00:00:00"+00:00:00+-}+timeOfDay :: Decoder Time.TimeOfDay+timeOfDay = Decoder {..}+  where+    extract (TimeLiteral t _) = pure t+    extract  expr             = typeError expected expr++    expected = pure Time++{-| Decode `Time.Day`++>>> input day "2000-01-01"+2000-01-01+-}+day :: Decoder Time.Day+day = Decoder {..}+  where+    extract (DateLiteral d) = pure d+    extract  expr           = typeError expected expr++    expected = pure Date++{-| Decode `Time.TimeZone`++>>> input timeZone "+00:00"++0000+-}+timeZone :: Decoder Time.TimeZone+timeZone = Decoder {..}+  where+    extract (TimeZoneLiteral z) = pure z+    extract  expr               = typeError expected expr++    expected = pure TimeZone++{-| Decode `Time.LocalTime`++>>> input localTime "2020-01-01T12:34:56"+2020-01-01 12:34:56+-}+localTime :: Decoder Time.LocalTime+localTime = record $+  Time.LocalTime+    <$> field "date" day+    <*> field "time" timeOfDay++{-| Decode `Time.ZonedTime`++>>> input zonedTime "2020-01-01T12:34:56+02:00"+2020-01-01 12:34:56 +0200+-}+zonedTime :: Decoder Time.ZonedTime+zonedTime = record $+  adapt+    <$> field "date" day+    <*> field "time" timeOfDay+    <*> field "timeZone" timeZone+  where+    adapt date time = Time.ZonedTime (Time.LocalTime date time)++{-| Decode `Time.UTCTime`++>>> input utcTime "2020-01-01T12:34:56+02:00"+2020-01-01 10:34:56 UTC+-}+utcTime :: Decoder Time.UTCTime+utcTime = Time.zonedTimeToUTC <$> zonedTime++{-| Decode `Time.DayOfWeek`++>>> input dayOfWeek "< Sunday | Monday | Tuesday | Wednesday | Thursday | Friday | Saturday >.Monday"+Monday+-}+dayOfWeek :: Decoder Time.DayOfWeek+dayOfWeek = Decoder{..}+  where+    extract expr@(Field _ FieldSelection{ fieldSelectionLabel }) =+        case fieldSelectionLabel of+            "Sunday"    -> pure Time.Sunday+            "Monday"    -> pure Time.Monday+            "Tuesday"   -> pure Time.Tuesday+            "Wednesday" -> pure Time.Wednesday+            "Thursday"  -> pure Time.Thursday+            "Friday"    -> pure Time.Friday+            "Saturday"  -> pure Time.Saturday+            _           -> typeError expected expr+    extract expr =+        typeError expected expr++    expected =+        pure+            (Union+                (Dhall.Map.fromList+                    [ ("Sunday", Nothing)+                    , ("Monday", Nothing)+                    , ("Tuesday", Nothing)+                    , ("Wednesday", Nothing)+                    , ("Thursday", Nothing)+                    , ("Friday", Nothing)+                    , ("Saturday", Nothing)+                    ]+                )+            )++{-| Decode a `Maybe`.++>>> input (maybe natural) "Some 1"+Just 1+-}+maybe :: Decoder a -> Decoder (Maybe a)+maybe (Decoder extractIn expectedIn) = Decoder extractOut expectedOut+  where+    extractOut (Some e    ) = fmap Just (extractIn e)+    extractOut (App None _) = pure Nothing+    extractOut expr         = typeError expectedOut expr++    expectedOut = App Optional <$> expectedIn++{-| Decode a `Seq`.++>>> input (sequence natural) "[1, 2, 3]"+fromList [1,2,3]+-}+sequence :: Decoder a -> Decoder (Seq a)+sequence (Decoder extractIn expectedIn) = Decoder extractOut expectedOut+  where+    extractOut (ListLit _ es) = traverse extractIn es+    extractOut expr           = typeError expectedOut expr++    expectedOut = App List <$> expectedIn++{-| Decode a list.++>>> input (list natural) "[1, 2, 3]"+[1,2,3]+-}+list :: Decoder a -> Decoder [a]+list = fmap Data.Foldable.toList . sequence++{-| Decode a `Vector`.++>>> input (vector natural) "[1, 2, 3]"+[1,2,3]+-}+vector :: Decoder a -> Decoder (Vector a)+vector = fmap Data.Vector.fromList . list++{-| Decode a Dhall function into a Haskell function.++>>> f <- input (function inject bool) "Natural/even" :: IO (Natural -> Bool)+>>> f 0+True+>>> f 1+False+-}+function+    :: Encoder a+    -> Decoder b+    -> Decoder (a -> b)+function = functionWith defaultInputNormalizer++{-| Decode a Dhall function into a Haskell function using the specified normalizer.++>>> f <- input (functionWith defaultInputNormalizer inject bool) "Natural/even" :: IO (Natural -> Bool)+>>> f 0+True+>>> f 1+False+-}+functionWith+    :: InputNormalizer+    -> Encoder a+    -> Decoder b+    -> Decoder (a -> b)+functionWith inputNormalizer (Encoder {..}) (Decoder extractIn expectedIn) =+    Decoder extractOut expectedOut+  where+    normalizer_ = Just (getInputNormalizer inputNormalizer)++    extractOut e = pure (\i -> case extractIn (Core.normalizeWith normalizer_ (App e (embed i))) of+        Success o  -> o+        Failure _e -> error "FromDhall: You cannot decode a function if it does not have the correct type" )++    expectedOut = Pi mempty "_" declared <$> expectedIn++{-| Decode a `Data.Set.Set` from a `List`.++>>> input (setIgnoringDuplicates natural) "[1, 2, 3]"+fromList [1,2,3]++Duplicate elements are ignored.++>>> input (setIgnoringDuplicates natural) "[1, 1, 3]"+fromList [1,3]++-}+setIgnoringDuplicates :: (Ord a) => Decoder a -> Decoder (Data.Set.Set a)+setIgnoringDuplicates = fmap Data.Set.fromList . list++{-| Decode a `Data.HashSet.HashSet` from a `List`.++>>> input (hashSetIgnoringDuplicates natural) "[1, 2, 3]"+fromList [1,2,3]++Duplicate elements are ignored.++>>> input (hashSetIgnoringDuplicates natural) "[1, 1, 3]"+fromList [1,3]++-}+hashSetIgnoringDuplicates :: (Hashable a, Ord a)+                          => Decoder a+                          -> Decoder (Data.HashSet.HashSet a)+hashSetIgnoringDuplicates = fmap Data.HashSet.fromList . list++{-| Decode a `Data.Set.Set` from a `List` with distinct elements.++>>> input (setFromDistinctList natural) "[1, 2, 3]"+fromList [1,2,3]++An error is thrown if the list contains duplicates.++> >>> input (setFromDistinctList natural) "[1, 1, 3]"+> *** Exception: Error: Failed extraction+>+> The expression type-checked successfully but the transformation to the target+> type failed with the following error:+>+> One duplicate element in the list: 1+>++> >>> input (setFromDistinctList natural) "[1, 1, 3, 3]"+> *** Exception: Error: Failed extraction+>+> The expression type-checked successfully but the transformation to the target+> type failed with the following error:+>+> 2 duplicates were found in the list, including 1+>++-}+setFromDistinctList :: (Ord a, Show a) => Decoder a -> Decoder (Data.Set.Set a)+setFromDistinctList = setHelper Data.Set.size Data.Set.fromList++{-| Decode a `Data.HashSet.HashSet` from a `List` with distinct elements.++>>> input (hashSetFromDistinctList natural) "[1, 2, 3]"+fromList [1,2,3]++An error is thrown if the list contains duplicates.++> >>> input (hashSetFromDistinctList natural) "[1, 1, 3]"+> *** Exception: Error: Failed extraction+>+> The expression type-checked successfully but the transformation to the target+> type failed with the following error:+>+> One duplicate element in the list: 1+>++> >>> input (hashSetFromDistinctList natural) "[1, 1, 3, 3]"+> *** Exception: Error: Failed extraction+>+> The expression type-checked successfully but the transformation to the target+> type failed with the following error:+>+> 2 duplicates were found in the list, including 1+>++-}+hashSetFromDistinctList :: (Hashable a, Ord a, Show a)+                        => Decoder a+                        -> Decoder (Data.HashSet.HashSet a)+hashSetFromDistinctList = setHelper Data.HashSet.size Data.HashSet.fromList+++setHelper :: (Eq a, Foldable t, Show a)+          => (t a -> Int)+          -> ([a] -> t a)+          -> Decoder a+          -> Decoder (t a)+setHelper size toSet (Decoder extractIn expectedIn) = Decoder extractOut expectedOut+  where+    extractOut (ListLit _ es) = case traverse extractIn es of+        Success vSeq+            | sameSize               -> Success vSet+            | otherwise              -> extractError err+          where+            vList = Data.Foldable.toList vSeq+            vSet = toSet vList+            sameSize = size vSet == Data.Sequence.length vSeq+            duplicates = vList List.\\ Data.Foldable.toList vSet+            err | length duplicates == 1 =+                     "One duplicate element in the list: "+                     <> (Data.Text.pack $ show $ head duplicates)+                | otherwise              = Data.Text.pack $ unwords+                     [ show $ length duplicates+                     , "duplicates were found in the list, including"+                     , show $ head duplicates+                     ]+        Failure f -> Failure f+    extractOut expr = typeError expectedOut expr++    expectedOut = App List <$> expectedIn++{-| Decode a `Map` from a @toMap@ expression or generally a @Prelude.Map.Type@.++>>> input (Dhall.map strictText bool) "toMap { a = True, b = False }"+fromList [("a",True),("b",False)]+>>> input (Dhall.map strictText bool) "[ { mapKey = \"foo\", mapValue = True } ]"+fromList [("foo",True)]++If there are duplicate @mapKey@s, later @mapValue@s take precedence:++>>> let expr = "[ { mapKey = 1, mapValue = True }, { mapKey = 1, mapValue = False } ]"+>>> input (Dhall.map natural bool) expr+fromList [(1,False)]++-}+map :: Ord k => Decoder k -> Decoder v -> Decoder (Map k v)+map k v = fmap Data.Map.fromList (list (pairFromMapEntry k v))++{-| Decode a `HashMap` from a @toMap@ expression or generally a @Prelude.Map.Type@.++>>> fmap (List.sort . HashMap.toList) (input (Dhall.hashMap strictText bool) "toMap { a = True, b = False }")+[("a",True),("b",False)]+>>> fmap (List.sort . HashMap.toList) (input (Dhall.hashMap strictText bool) "[ { mapKey = \"foo\", mapValue = True } ]")+[("foo",True)]++If there are duplicate @mapKey@s, later @mapValue@s take precedence:++>>> let expr = "[ { mapKey = 1, mapValue = True }, { mapKey = 1, mapValue = False } ]"+>>> input (Dhall.hashMap natural bool) expr+fromList [(1,False)]++-}+hashMap :: (Eq k, Hashable k) => Decoder k -> Decoder v -> Decoder (HashMap k v)+hashMap k v = fmap HashMap.fromList (list (pairFromMapEntry k v))++{-| Decode a tuple from a @Prelude.Map.Entry@ record.++>>> input (pairFromMapEntry strictText natural) "{ mapKey = \"foo\", mapValue = 3 }"+("foo",3)+-}+pairFromMapEntry :: Decoder k -> Decoder v -> Decoder (k, v)+pairFromMapEntry k v = Decoder extractOut expectedOut+  where+    extractOut (RecordLit kvs)+        | Just key <- Core.recordFieldValue <$> Dhall.Map.lookup "mapKey" kvs+        , Just value <- Core.recordFieldValue <$> Dhall.Map.lookup "mapValue" kvs+            = liftA2 (,) (extract k key) (extract v value)+    extractOut expr = typeError expectedOut expr++    expectedOut = do+        k' <- Core.makeRecordField <$> expected k+        v' <- Core.makeRecordField <$> expected v+        pure $ Record $ Dhall.Map.fromList+            [ ("mapKey", k')+            , ("mapValue", v')]++{-| Decode @()@ from an empty record.++>>> input unit "{=}"  -- GHC doesn't print the result if it is ()++-}+unit :: Decoder ()+unit = Decoder {..}+  where+    extract (RecordLit fields)+        | Data.Foldable.null fields = pure ()+    extract expr = typeError expected expr++    expected = pure $ Record mempty++{-| Decode 'Void' from an empty union.++Since @<>@ is uninhabited, @'Dhall.input' 'void'@ will always fail.+-}+void :: Decoder Void+void = union mempty++{-| Decode a `String`++>>> input string "\"ABC\""+"ABC"++-}+string :: Decoder String+string = Data.Text.Lazy.unpack <$> lazyText++{-| Given a pair of `Decoder`s, decode a tuple-record into their pairing.++>>> input (pair natural bool) "{ _1 = 42, _2 = False }"+(42,False)+-}+pair :: Decoder a -> Decoder b -> Decoder (a, b)+pair l r = Decoder extractOut expectedOut+  where+    extractOut expr@(RecordLit fields) =+      (,) <$> Data.Maybe.maybe (typeError expectedOut expr) (extract l)+                (Core.recordFieldValue <$> Dhall.Map.lookup "_1" fields)+          <*> Data.Maybe.maybe (typeError expectedOut expr) (extract r)+                (Core.recordFieldValue <$> Dhall.Map.lookup "_2" fields)+    extractOut expr = typeError expectedOut expr++    expectedOut = do+        l' <- Core.makeRecordField <$> expected l+        r' <- Core.makeRecordField <$> expected r+        pure $ Record $ Dhall.Map.fromList+            [ ("_1", l')+            , ("_2", r')]++++{-| The 'RecordDecoder' applicative functor allows you to build a 'Decoder'+    from a Dhall record.++    For example, let's take the following Haskell data type:++>>> :{+data Project = Project+  { projectName :: Text+  , projectDescription :: Text+  , projectStars :: Natural+  }+:}++    And assume that we have the following Dhall record that we would like to+    parse as a @Project@:++> { name =+>     "dhall-haskell"+> , description =+>     "A configuration language guaranteed to terminate"+> , stars =+>     289+> }++    Our decoder has type 'Decoder' @Project@, but we can't build that out of any+    smaller decoders, as 'Decoder's cannot be combined (they are only 'Functor's).+    However, we can use a 'RecordDecoder' to build a 'Decoder' for @Project@:++>>> :{+project :: Decoder Project+project =+  record+    ( Project <$> field "name" strictText+              <*> field "description" strictText+              <*> field "stars" natural+    )+:}+-}+newtype RecordDecoder a =+  RecordDecoder+    ( Data.Functor.Product.Product+        ( Control.Applicative.Const+            (Dhall.Map.Map Text (Expector (Expr Src Void)))+        )+        ( Data.Functor.Compose.Compose ((->) (Expr Src Void)) (Extractor Src Void)+        )+        a+    )+  deriving (Functor, Applicative)++-- | Run a 'RecordDecoder' to build a 'Decoder'.+record :: RecordDecoder a -> Dhall.Marshal.Decode.Decoder a+record+    (RecordDecoder+        (Data.Functor.Product.Pair+            (Control.Applicative.Const fields)+            (Data.Functor.Compose.Compose extract)+        )+    ) = Decoder {..}+  where+    expected = Record <$> traverse (fmap Core.makeRecordField) fields++-- | Parse a single field of a record.+field :: Text -> Decoder a -> RecordDecoder a+field key (Decoder {..}) =+  RecordDecoder+    ( Data.Functor.Product.Pair+        ( Control.Applicative.Const+            (Dhall.Map.singleton key expected)+        )+        ( Data.Functor.Compose.Compose extractBody )+    )+  where+    extractBody expr@(RecordLit fields) = case Core.recordFieldValue <$> Dhall.Map.lookup key fields of+      Just v -> extract v+      _      -> typeError expected expr+    extractBody expr = typeError expected expr++++{-| The 'UnionDecoder' monoid allows you to build a 'Decoder' from a Dhall union.++    For example, let's take the following Haskell data type:++>>> :{+data Status = Queued Natural+            | Result Text+            | Errored Text+:}++    And assume that we have the following Dhall union that we would like to+    parse as a @Status@:++> < Result : Text+> | Queued : Natural+> | Errored : Text+> >.Result "Finish successfully"++    Our decoder has type 'Decoder' @Status@, but we can't build that out of any+    smaller decoders, as 'Decoder's cannot be combined (they are only 'Functor's).+    However, we can use a 'UnionDecoder' to build a 'Decoder' for @Status@:++>>> :{+status :: Decoder Status+status = union+  (  ( Queued  <$> constructor "Queued"  natural )+  <> ( Result  <$> constructor "Result"  strictText )+  <> ( Errored <$> constructor "Errored" strictText )+  )+:}++-}+newtype UnionDecoder a =+    UnionDecoder+      ( Data.Functor.Compose.Compose (Dhall.Map.Map Text) Decoder a )+  deriving (Functor)++instance Semigroup (UnionDecoder a) where+    (<>) = coerce ((<>) :: Dhall.Map.Map Text (Decoder a) -> Dhall.Map.Map Text (Decoder a) -> Dhall.Map.Map Text (Decoder a))++instance Monoid (UnionDecoder a) where+    mempty = coerce (mempty :: Dhall.Map.Map Text (Decoder a))++-- | Run a 'UnionDecoder' to build a 'Decoder'.+union :: UnionDecoder a -> Decoder a+union (UnionDecoder (Data.Functor.Compose.Compose mp)) = Decoder {..}+  where+    extract expr = case expected' of+        Failure e -> Failure $ fmap ExpectedTypeError e+        Success x -> extract' expr x++    extract' e0 mp' = Data.Maybe.maybe (typeError expected e0) (uncurry Dhall.Marshal.Decode.extract) $ do+        (fld, e1, rest) <- extractUnionConstructor e0++        t <- Dhall.Map.lookup fld mp++        guard $+            Core.Union rest `Core.judgmentallyEqual` Core.Union (Dhall.Map.delete fld mp')++        pure (t, e1)++    expected = Union <$> expected'++    expected' = traverse (fmap notEmptyRecord . Dhall.Marshal.Decode.expected) mp++-- | Parse a single constructor of a union.+constructor :: Text -> Decoder a -> UnionDecoder a+constructor key valueDecoder = UnionDecoder+    ( Data.Functor.Compose.Compose (Dhall.Map.singleton key valueDecoder) )++++{-| A newtype suitable for collecting one or more errors.+-}+newtype DhallErrors e = DhallErrors+   { getErrors :: NonEmpty e+   } deriving (Eq, Functor, Semigroup)++instance (Show (DhallErrors e), Typeable e) => Exception (DhallErrors e)++{-| Render a given prefix and some errors to a string.+-}+showDhallErrors :: Show e => String -> DhallErrors e -> String+showDhallErrors _   (DhallErrors (e :| [])) = show e+showDhallErrors ctx (DhallErrors es) = prefix <> (unlines . Data.List.NonEmpty.toList . fmap show $ es)+  where+    prefix =+        "Multiple errors were encountered" ++ ctx ++ ": \n\+        \                                               \n"++{-| One or more errors returned from extracting a Dhall expression to a+    Haskell expression.+-}+type ExtractErrors s a = DhallErrors (ExtractError s a)++instance (Pretty s, Pretty a, Typeable s, Typeable a) => Show (ExtractErrors s a) where+    show = showDhallErrors " during extraction"++{-| Extraction of a value can fail for two reasons, either a type mismatch (which should not happen,+    as expressions are type-checked against the expected type before being passed to @extract@), or+    a term-level error, described with a freeform text value.+-}+data ExtractError s a =+    TypeMismatch (InvalidDecoder s a)+  | ExpectedTypeError ExpectedTypeError+  | ExtractError Text+  deriving (Eq)++instance (Pretty s, Pretty a, Typeable s, Typeable a) => Show (ExtractError s a) where+  show (TypeMismatch e)      = show e+  show (ExpectedTypeError e) = show e+  show (ExtractError es)     = unlines+      [ _ERROR <> ": Failed extraction                                                   "+      , "                                                                                "+      , "The expression type-checked successfully but the transformation to the target   "+      , "type failed with the following error:                                           "+      , "                                                                                "+      , Data.Text.unpack es+      , "                                                                                "+      ]++instance (Pretty s, Pretty a, Typeable s, Typeable a) => Exception (ExtractError s a)++{-| Useful synonym for the `Validation` type used when marshalling Dhall+    expressions.+-}+type Extractor s a = Validation (ExtractErrors s a)++{-| Generate a type error during extraction by specifying the expected type+    and the actual type.+    The expected type is not yet determined.+-}+typeError :: Expector (Expr s a) -> Expr s a -> Extractor s a b+typeError expected actual = Failure $ case expected of+    Failure e         -> fmap ExpectedTypeError e+    Success expected' -> DhallErrors $ pure $ TypeMismatch $ InvalidDecoder expected' actual++-- | Turn a `Data.Text.Text` message into an extraction failure.+extractError :: Text -> Extractor s a b+extractError = Failure . DhallErrors . pure . ExtractError++{-| Useful synonym for the equivalent `Either` type used when marshalling Dhall+    code.+-}+type MonadicExtractor s a = Either (ExtractErrors s a)++-- | Switches from an @Applicative@ extraction result, able to accumulate errors,+-- to a @Monad@ extraction result, able to chain sequential operations.+toMonadic :: Extractor s a b -> MonadicExtractor s a b+toMonadic = validationToEither++-- | Switches from a @Monad@ extraction result, able to chain sequential errors,+-- to an @Applicative@ extraction result, able to accumulate errors.+fromMonadic :: MonadicExtractor s a b -> Extractor s a b+fromMonadic = eitherToValidation++{-| Every `Decoder` must obey the contract that if an expression's type matches+    the `expected` type then the `extract` function must not fail with a type+    error.  However, decoding may still fail for other reasons (such as the+    decoder for `Data.Map.Set`s rejecting a Dhall @List@ with duplicate+    elements).++    This error type is used to indicate an internal error in the implementation+    of a `Decoder` where the expected type matched the Dhall expression, but the+    expression supplied to the extraction function did not match the expected+    type.  If this happens that means that the `Decoder` itself needs to be+    fixed.+-}+data InvalidDecoder s a = InvalidDecoder+  { invalidDecoderExpected   :: Expr s a+  , invalidDecoderExpression :: Expr s a+  }+  deriving (Eq, Typeable)++instance (Pretty s, Typeable s, Pretty a, Typeable a) => Exception (InvalidDecoder s a)++instance (Pretty s, Pretty a, Typeable s, Typeable a) => Show (InvalidDecoder s a) where+    show InvalidDecoder { .. } = unlines+        [ _ERROR <> ": Invalid Dhall.Decoder                                               "+        , "                                                                                "+        , "Every Decoder must provide an extract function that does not fail with a type   "+        , "error if an expression matches the expected type.  You provided a Decoder that  "+        , "disobeys this contract                                                          "+        , "                                                                                "+        , "The Decoder provided has the expected dhall type:                               "+        , "                                                                                "+        , show (Dhall.Util.insert invalidDecoderExpected)+        , "                                                                                "+        , "and it threw a type error during extraction from the well-typed expression:     "+        , "                                                                                "+        , show (Dhall.Util.insert invalidDecoderExpression)+        , "                                                                                "+        ]++{-| Useful synonym for the `Validation` type used when marshalling Dhall+    expressions.+-}+type Expector = Validation ExpectedTypeErrors++{-| One or more errors returned when determining the Dhall type of a+    Haskell expression.+-}+type ExpectedTypeErrors = DhallErrors ExpectedTypeError++{-| Error type used when determining the Dhall type of a Haskell expression.+-}+data ExpectedTypeError = RecursiveTypeError+    deriving (Eq, Show)++instance Exception ExpectedTypeError++instance Show ExpectedTypeErrors where+    show = showDhallErrors " while determining the expected type"++_ERROR :: String+_ERROR = "\ESC[1;31mError\ESC[0m"
+ src/Dhall/Marshal/Encode.hs view
@@ -0,0 +1,1068 @@+{-# LANGUAGE ConstraintKinds            #-}+{-# LANGUAGE DefaultSignatures          #-}+{-# LANGUAGE FlexibleContexts           #-}+{-# LANGUAGE FlexibleInstances          #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE OverloadedStrings          #-}+{-# LANGUAGE RankNTypes                 #-}+{-# LANGUAGE RecordWildCards            #-}+{-# LANGUAGE ScopedTypeVariables        #-}+{-# LANGUAGE TupleSections              #-}+{-# LANGUAGE TypeApplications           #-}+{-# LANGUAGE TypeOperators              #-}+{-# LANGUAGE UndecidableInstances       #-}++{-| Please read the "Dhall.Tutorial" module, which contains a tutorial explaining+    how to use the language, the compiler, and this library+-}++module Dhall.Marshal.Encode+    ( -- * General+      Encoder(..)+    , ToDhall(..)+    , Inject+    , inject++      -- * Building encoders++      -- ** Records+    , RecordEncoder(..)+    , recordEncoder+    , encodeField+    , encodeFieldWith+      -- ** Unions+    , UnionEncoder(..)+    , unionEncoder+    , encodeConstructor+    , encodeConstructorWith+    , (>|<)++      -- * Generic encoding+    , GenericToDhall(..)+    , genericToDhall+    , genericToDhallWith+    , genericToDhallWithInputNormalizer+    , InterpretOptions(..)+    , SingletonConstructors(..)+    , defaultInterpretOptions++      -- * Miscellaneous+    , InputNormalizer(..)+    , defaultInputNormalizer+    , Result+    , (>$<)+    , (>*<)++    -- * Re-exports+    , Natural+    , Seq+    , Text+    , Vector+    , Generic+    ) where++import Control.Monad.Trans.State.Strict+import Data.Functor.Contravariant           (Contravariant (..), Op (..), (>$<))+import Data.Functor.Contravariant.Divisible (Divisible (..), divided)+import Dhall.Parser                         (Src (..))+import Dhall.Syntax+    ( Chunks (..)+    , DhallDouble (..)+    , Expr (..)+    )+import GHC.Generics+import Prelude                              hiding (maybe, sequence)++import qualified Control.Applicative+import qualified Data.ByteString+import qualified Data.ByteString.Lazy+import qualified Data.ByteString.Short+import qualified Data.Functor.Product+import qualified Data.HashMap.Strict   as HashMap+import qualified Data.HashSet+import qualified Data.Map+import qualified Data.Scientific+import qualified Data.Sequence+import qualified Data.Set+import qualified Data.Text+import qualified Data.Text.Lazy+import qualified Data.Text.Short+import qualified Data.Time             as Time+import qualified Data.Vector+import qualified Data.Void+import qualified Dhall.Core            as Core+import qualified Dhall.Map++import Dhall.Marshal.Internal++-- $setup+-- >>> :set -XRecordWildCards+-- >>> import Dhall.Pretty.Internal (prettyExpr)++{-| An @(Encoder a)@ represents a way to marshal a value of type @\'a\'@ from+    Haskell into Dhall.+-}+data Encoder a = Encoder+    { embed    :: a -> Expr Src Void+    -- ^ Embeds a Haskell value as a Dhall expression+    , declared :: Expr Src Void+    -- ^ Dhall type of the Haskell value+    }++instance Contravariant Encoder where+    contramap f (Encoder embed declared) = Encoder embed' declared+      where+        embed' x = embed (f x)++{-| This class is used by `Dhall.Marshal.Decode.FromDhall` instance for functions:++> instance (ToDhall a, FromDhall b) => FromDhall (a -> b)++    You can convert Dhall functions with "simple" inputs (i.e. instances of this+    class) into Haskell functions.  This works by:++    * Marshaling the input to the Haskell function into a Dhall expression (i.e.+      @x :: Expr Src Void@)+    * Applying the Dhall function (i.e. @f :: Expr Src Void@) to the Dhall input+      (i.e. @App f x@)+    * Normalizing the syntax tree (i.e. @normalize (App f x)@)+    * Marshaling the resulting Dhall expression back into a Haskell value++    This class auto-generates a default implementation for types that+    implement `Generic`.  This does not auto-generate an instance for recursive+    types.++    The default instance can be tweaked using 'genericToDhallWith'/'genericToDhallWithInputNormalizer'+    and custom 'InterpretOptions', or using+    [DerivingVia](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#extension-DerivingVia)+    and 'Dhall.Deriving.Codec' from "Dhall.Deriving".+-}+class ToDhall a where+    injectWith :: InputNormalizer -> Encoder a+    default injectWith+        :: (Generic a, GenericToDhall (Rep a)) => InputNormalizer -> Encoder a+    injectWith _ = genericToDhall++-- | A compatibility alias for `ToDhall`+type Inject = ToDhall+{-# DEPRECATED Inject "Use ToDhall instead" #-}++{-| Use the default input normalizer for injecting a value.++> inject = injectWith defaultInputNormalizer+-}+inject :: ToDhall a => Encoder a+inject = injectWith defaultInputNormalizer++++instance ToDhall Void where+    injectWith _ = Encoder {..}+      where+        embed = Data.Void.absurd++        declared = Union mempty++instance ToDhall Bool where+    injectWith _ = Encoder {..}+      where+        embed = BoolLit++        declared = Bool++instance ToDhall Data.ByteString.Short.ShortByteString where+    injectWith options =+        contramap Data.ByteString.Short.fromShort (injectWith options)++instance ToDhall Data.ByteString.Lazy.ByteString where+    injectWith options =+        contramap Data.ByteString.Lazy.toStrict (injectWith options)++instance ToDhall Data.ByteString.ByteString where+    injectWith _ = Encoder {..}+      where+        embed bytes = BytesLit bytes++        declared = Bytes++instance ToDhall Data.Text.Short.ShortText where+    injectWith _ = Encoder {..}+      where+        embed text =+            TextLit (Chunks [] (Data.Text.Short.toText text))++        declared = Text++instance ToDhall Data.Text.Lazy.Text where+    injectWith _ = Encoder {..}+      where+        embed text =+            TextLit (Chunks [] (Data.Text.Lazy.toStrict text))++        declared = Text++instance ToDhall Text where+    injectWith _ = Encoder {..}+      where+        embed text = TextLit (Chunks [] text)++        declared = Text++instance {-# OVERLAPS #-} ToDhall String where+    injectWith inputNormalizer =+        contramap Data.Text.pack (injectWith inputNormalizer :: Encoder Text)++instance ToDhall Natural where+    injectWith _ = Encoder {..}+      where+        embed = NaturalLit++        declared = Natural++instance ToDhall Integer where+    injectWith _ = Encoder {..}+      where+        embed = IntegerLit++        declared = Integer++instance ToDhall Int where+    injectWith _ = Encoder {..}+      where+        embed = IntegerLit . toInteger++        declared = Integer++instance ToDhall Int8 where+    injectWith _ = Encoder {..}+      where+        embed = IntegerLit . toInteger++        declared = Integer++instance ToDhall Int16 where+    injectWith _ = Encoder {..}+      where+        embed = IntegerLit . toInteger++        declared = Integer++instance ToDhall Int32 where+    injectWith _ = Encoder {..}+      where+        embed = IntegerLit . toInteger++        declared = Integer++instance ToDhall Int64 where+    injectWith _ = Encoder {..}+      where+        embed = IntegerLit . toInteger++        declared = Integer++{-| Encode a 'Word' to a Dhall @Natural@.++>>> embed inject (12 :: Word)+NaturalLit 12+-}+instance ToDhall Word where+    injectWith _ = Encoder {..}+      where+        embed = NaturalLit . fromIntegral++        declared = Natural++{-| Encode a 'Word8' to a Dhall @Natural@.++>>> embed inject (12 :: Word8)+NaturalLit 12+-}+instance ToDhall Word8 where+    injectWith _ = Encoder {..}+      where+        embed = NaturalLit . fromIntegral++        declared = Natural++{-| Encode a 'Word16' to a Dhall @Natural@.++>>> embed inject (12 :: Word16)+NaturalLit 12+-}+instance ToDhall Word16 where+    injectWith _ = Encoder {..}+      where+        embed = NaturalLit . fromIntegral++        declared = Natural++{-| Encode a 'Word32' to a Dhall @Natural@.++>>> embed inject (12 :: Word32)+NaturalLit 12+-}+instance ToDhall Word32 where+    injectWith _ = Encoder {..}+      where+        embed = NaturalLit . fromIntegral++        declared = Natural++{-| Encode a 'Word64' to a Dhall @Natural@.++>>> embed inject (12 :: Word64)+NaturalLit 12+-}+instance ToDhall Word64 where+    injectWith _ = Encoder {..}+      where+        embed = NaturalLit . fromIntegral++        declared = Natural++instance ToDhall Double where+    injectWith _ = Encoder {..}+      where+        embed = DoubleLit . DhallDouble++        declared = Double++instance ToDhall Scientific where+    injectWith inputNormalizer =+        contramap Data.Scientific.toRealFloat (injectWith inputNormalizer :: Encoder Double)++instance ToDhall () where+    injectWith _ = Encoder {..}+      where+        embed = const (RecordLit mempty)++        declared = Record mempty++instance ToDhall a => ToDhall (Maybe a) where+    injectWith inputNormalizer = Encoder embedOut declaredOut+      where+        embedOut (Just x ) = Some (embedIn x)+        embedOut  Nothing  = App None declaredIn++        Encoder embedIn declaredIn = injectWith inputNormalizer++        declaredOut = App Optional declaredIn++instance ToDhall a => ToDhall (Seq a) where+    injectWith inputNormalizer = Encoder embedOut declaredOut+      where+        embedOut xs = ListLit listType (fmap embedIn xs)+          where+            listType+                | null xs   = Just (App List declaredIn)+                | otherwise = Nothing++        declaredOut = App List declaredIn++        Encoder embedIn declaredIn = injectWith inputNormalizer++instance ToDhall a => ToDhall [a] where+    injectWith = fmap (contramap Data.Sequence.fromList) injectWith++instance ToDhall a => ToDhall (Vector a) where+    injectWith = fmap (contramap Data.Vector.toList) injectWith++instance ToDhall Time.TimeOfDay where+    injectWith _ = Encoder {..}+      where+        embed timeOfDay = TimeLiteral timeOfDay 12++        declared = Time++instance ToDhall Time.Day where+    injectWith _ = Encoder {..}+      where+        embed = DateLiteral++        declared = Date++instance ToDhall Time.TimeZone where+    injectWith _ = Encoder {..}+      where+        embed = TimeZoneLiteral++        declared = TimeZone++instance ToDhall Time.LocalTime where+    injectWith _ = recordEncoder $+      adapt+        >$< encodeField "date"+        >*< encodeField "time"+      where+        adapt (Time.LocalTime date time) = (date, time)++instance ToDhall Time.ZonedTime where+    injectWith _ = recordEncoder $+      adapt+        >$< encodeField "date"+        >*< encodeField "time"+        >*< encodeField "timeZone"+      where+        adapt (Time.ZonedTime (Time.LocalTime date time) timeZone) = (date, (time, timeZone))++instance ToDhall Time.UTCTime where+    injectWith = contramap (Time.utcToZonedTime Time.utc) . injectWith++instance ToDhall Time.DayOfWeek where+    injectWith _ = Encoder{..}+      where+        embed Time.Sunday =+            Field declared (Core.makeFieldSelection "Sunday")+        embed Time.Monday =+            Field declared (Core.makeFieldSelection "Monday" )+        embed Time.Tuesday =+            Field declared (Core.makeFieldSelection "Tuesday")+        embed Time.Wednesday =+            Field declared (Core.makeFieldSelection "Wednesday")+        embed Time.Thursday =+            Field declared (Core.makeFieldSelection "Thursday")+        embed Time.Friday =+            Field declared (Core.makeFieldSelection "Friday")+        embed Time.Saturday =+            Field declared (Core.makeFieldSelection "Saturday")++        declared =+            Union+                (Dhall.Map.fromList+                    [ ("Sunday", Nothing)+                    , ("Monday", Nothing)+                    , ("Tuesday", Nothing)+                    , ("Wednesday", Nothing)+                    , ("Thursday", Nothing)+                    , ("Friday", Nothing)+                    , ("Saturday", Nothing)+                    ]+                )++{-| Note that the output list will be sorted.++>>> let x = Data.Set.fromList ["mom", "hi" :: Text]+>>> prettyExpr $ embed inject x+[ "hi", "mom" ]++-}+instance ToDhall a => ToDhall (Data.Set.Set a) where+    injectWith = fmap (contramap Data.Set.toAscList) injectWith++-- | Note that the output list may not be sorted+instance ToDhall a => ToDhall (Data.HashSet.HashSet a) where+    injectWith = fmap (contramap Data.HashSet.toList) injectWith++instance (ToDhall a, ToDhall b) => ToDhall (a, b)++{-| Embed a `Data.Map` as a @Prelude.Map.Type@.++>>> prettyExpr $ embed inject (Data.Map.fromList [(1 :: Natural, True)])+[ { mapKey = 1, mapValue = True } ]++>>> prettyExpr $ embed inject (Data.Map.fromList [] :: Data.Map.Map Natural Bool)+[] : List { mapKey : Natural, mapValue : Bool }++-}+instance (ToDhall k, ToDhall v) => ToDhall (Data.Map.Map k v) where+    injectWith inputNormalizer = Encoder embedOut declaredOut+      where+        embedOut m = ListLit listType (mapEntries m)+          where+            listType+                | Data.Map.null m = Just declaredOut+                | otherwise       = Nothing++        declaredOut = App List (Record $ Dhall.Map.fromList+                          [ ("mapKey", Core.makeRecordField declaredK)+                          , ("mapValue", Core.makeRecordField declaredV)+                          ])++        mapEntries = Data.Sequence.fromList . fmap recordPair . Data.Map.toList+        recordPair (k, v) = RecordLit $ Dhall.Map.fromList+                                [ ("mapKey", Core.makeRecordField $ embedK k)+                                , ("mapValue", Core.makeRecordField $ embedV v)+                                ]++        Encoder embedK declaredK = injectWith inputNormalizer+        Encoder embedV declaredV = injectWith inputNormalizer++{-| Embed a `Data.HashMap` as a @Prelude.Map.Type@.++>>> prettyExpr $ embed inject (HashMap.fromList [(1 :: Natural, True)])+[ { mapKey = 1, mapValue = True } ]++>>> prettyExpr $ embed inject (HashMap.fromList [] :: HashMap Natural Bool)+[] : List { mapKey : Natural, mapValue : Bool }++-}+instance (ToDhall k, ToDhall v) => ToDhall (HashMap k v) where+    injectWith inputNormalizer = Encoder embedOut declaredOut+      where+        embedOut m = ListLit listType (mapEntries m)+          where+            listType+                | HashMap.null m = Just declaredOut+                | otherwise       = Nothing++        declaredOut = App List (Record $ Dhall.Map.fromList+                          [ ("mapKey", Core.makeRecordField declaredK)+                          , ("mapValue", Core.makeRecordField declaredV)+                          ])++        mapEntries = Data.Sequence.fromList . fmap recordPair . HashMap.toList+        recordPair (k, v) = RecordLit $ Dhall.Map.fromList+                                [ ("mapKey", Core.makeRecordField $ embedK k)+                                , ("mapValue", Core.makeRecordField $ embedV v)+                                ]++        Encoder embedK declaredK = injectWith inputNormalizer+        Encoder embedV declaredV = injectWith inputNormalizer++instance ToDhall (f (Result f)) => ToDhall (Result f) where+    injectWith inputNormalizer = Encoder {..}+      where+        embed = App "Make" . Dhall.Marshal.Encode.embed (injectWith inputNormalizer) . _unResult+        declared = "result"++instance forall f. (Functor f, ToDhall (f (Result f))) => ToDhall (Fix f) where+    injectWith inputNormalizer = Encoder {..}+      where+        embed fixf =+          Lam Nothing (Core.makeFunctionBinding "result" (Const Core.Type)) $+            Lam Nothing (Core.makeFunctionBinding "Make" makeType) $+              embed' . fixToResult $ fixf++        declared = Pi Nothing "result" (Const Core.Type) $ Pi Nothing "_" makeType "result"++        makeType = Pi Nothing "_" declared' "result"+        Encoder embed' _ = injectWith @(Dhall.Marshal.Internal.Result f) inputNormalizer+        Encoder _ declared' = injectWith @(f (Dhall.Marshal.Internal.Result f)) inputNormalizer++fixToResult :: Functor f => Fix f -> Result f+fixToResult (Fix x) = Result (fmap fixToResult x)++++{-| This is the underlying class that powers the `Dhall.Marshal.Decode.FromDhall` class's support+    for automatically deriving a generic implementation.+-}+class GenericToDhall f where+    genericToDhallWithNormalizer :: InputNormalizer -> InterpretOptions -> State Int (Encoder (f a))++instance GenericToDhall f => GenericToDhall (M1 D d f) where+    genericToDhallWithNormalizer inputNormalizer options = do+        res <- genericToDhallWithNormalizer inputNormalizer options+        pure (contramap unM1 res)++instance GenericToDhall f => GenericToDhall (M1 C c f) where+    genericToDhallWithNormalizer inputNormalizer options = do+        res <- genericToDhallWithNormalizer inputNormalizer options+        pure (contramap unM1 res)++instance (Selector s, ToDhall a) => GenericToDhall (M1 S s (K1 i a)) where+    genericToDhallWithNormalizer inputNormalizer InterpretOptions{..} = do+        let Encoder { embed = embed', declared = declared' } =+                injectWith inputNormalizer++        let n :: M1 S s (K1 i a) r+            n = undefined++        name <- fieldModifier <$> getSelName n++        let embed0 (M1 (K1 x)) = embed' x++        let embed1 (M1 (K1 x)) =+                RecordLit (Dhall.Map.singleton name (Core.makeRecordField $ embed' x))++        let embed =+                case singletonConstructors of+                    Bare                    -> embed0+                    Smart | selName n == "" -> embed0+                    _                       -> embed1++        let declared =+                case singletonConstructors of+                    Bare ->+                        declared'+                    Smart | selName n == "" ->+                        declared'+                    _ ->+                        Record (Dhall.Map.singleton name $ Core.makeRecordField declared')++        return (Encoder {..})++instance (Constructor c1, Constructor c2, GenericToDhall f1, GenericToDhall f2) => GenericToDhall (M1 C c1 f1 :+: M1 C c2 f2) where+    genericToDhallWithNormalizer inputNormalizer options@(InterpretOptions {..}) = pure (Encoder {..})+      where+        embed (L1 (M1 l)) =+            case notEmptyRecordLit (embedL l) of+                Nothing ->+                    Field declared $ Core.makeFieldSelection keyL+                Just valL ->+                    App (Field declared $ Core.makeFieldSelection keyL) valL++        embed (R1 (M1 r)) =+            case notEmptyRecordLit (embedR r) of+                Nothing ->+                    Field declared $ Core.makeFieldSelection keyR+                Just valR ->+                    App (Field declared $ Core.makeFieldSelection keyR) valR++        declared =+            Union+                (Dhall.Map.fromList+                    [ (keyL, notEmptyRecord declaredL)+                    , (keyR, notEmptyRecord declaredR)+                    ]+                )++        nL :: M1 i c1 f1 a+        nL = undefined++        nR :: M1 i c2 f2 a+        nR = undefined++        keyL = constructorModifier (Data.Text.pack (conName nL))+        keyR = constructorModifier (Data.Text.pack (conName nR))++        Encoder embedL declaredL = evalState (genericToDhallWithNormalizer inputNormalizer options) 1+        Encoder embedR declaredR = evalState (genericToDhallWithNormalizer inputNormalizer options) 1++instance (Constructor c, GenericToDhall (f :+: g), GenericToDhall h) => GenericToDhall ((f :+: g) :+: M1 C c h) where+    genericToDhallWithNormalizer inputNormalizer options@(InterpretOptions {..}) = pure (Encoder {..})+      where+        embed (L1 l) =+            case maybeValL of+                Nothing   -> Field declared $ Core.makeFieldSelection keyL+                Just valL -> App (Field declared $ Core.makeFieldSelection keyL) valL+          where+            (keyL, maybeValL) =+              unsafeExpectUnionLit "genericToDhallWithNormalizer (:+:)" (embedL l)+        embed (R1 (M1 r)) =+            case notEmptyRecordLit (embedR r) of+                Nothing   -> Field declared $ Core.makeFieldSelection keyR+                Just valR -> App (Field declared $ Core.makeFieldSelection keyR) valR++        nR :: M1 i c h a+        nR = undefined++        keyR = constructorModifier (Data.Text.pack (conName nR))++        declared = Union (Dhall.Map.insert keyR (notEmptyRecord declaredR) ktsL)++        Encoder embedL declaredL = evalState (genericToDhallWithNormalizer inputNormalizer options) 1+        Encoder embedR declaredR = evalState (genericToDhallWithNormalizer inputNormalizer options) 1++        ktsL = unsafeExpectUnion "genericToDhallWithNormalizer (:+:)" declaredL++instance (Constructor c, GenericToDhall f, GenericToDhall (g :+: h)) => GenericToDhall (M1 C c f :+: (g :+: h)) where+    genericToDhallWithNormalizer inputNormalizer options@(InterpretOptions {..}) = pure (Encoder {..})+      where+        embed (L1 (M1 l)) =+            case notEmptyRecordLit (embedL l) of+                Nothing   -> Field declared $ Core.makeFieldSelection keyL+                Just valL -> App (Field declared $ Core.makeFieldSelection keyL) valL+        embed (R1 r) =+            case maybeValR of+                Nothing   -> Field declared $ Core.makeFieldSelection keyR+                Just valR -> App (Field declared $ Core.makeFieldSelection keyR) valR+          where+            (keyR, maybeValR) =+                unsafeExpectUnionLit "genericToDhallWithNormalizer (:+:)" (embedR r)++        nL :: M1 i c f a+        nL = undefined++        keyL = constructorModifier (Data.Text.pack (conName nL))++        declared = Union (Dhall.Map.insert keyL (notEmptyRecord declaredL) ktsR)++        Encoder embedL declaredL = evalState (genericToDhallWithNormalizer inputNormalizer options) 1+        Encoder embedR declaredR = evalState (genericToDhallWithNormalizer inputNormalizer options) 1++        ktsR = unsafeExpectUnion "genericToDhallWithNormalizer (:+:)" declaredR++instance (GenericToDhall (f :+: g), GenericToDhall (h :+: i)) => GenericToDhall ((f :+: g) :+: (h :+: i)) where+    genericToDhallWithNormalizer inputNormalizer options = pure (Encoder {..})+      where+        embed (L1 l) =+            case maybeValL of+                Nothing   -> Field declared $ Core.makeFieldSelection keyL+                Just valL -> App (Field declared $ Core.makeFieldSelection keyL) valL+          where+            (keyL, maybeValL) =+                unsafeExpectUnionLit "genericToDhallWithNormalizer (:+:)" (embedL l)+        embed (R1 r) =+            case maybeValR of+                Nothing   -> Field declared $ Core.makeFieldSelection keyR+                Just valR -> App (Field declared $ Core.makeFieldSelection keyR) valR+          where+            (keyR, maybeValR) =+                unsafeExpectUnionLit "genericToDhallWithNormalizer (:+:)" (embedR r)++        declared = Union (Dhall.Map.union ktsL ktsR)++        Encoder embedL declaredL = evalState (genericToDhallWithNormalizer inputNormalizer options) 1+        Encoder embedR declaredR = evalState (genericToDhallWithNormalizer inputNormalizer options) 1++        ktsL = unsafeExpectUnion "genericToDhallWithNormalizer (:+:)" declaredL+        ktsR = unsafeExpectUnion "genericToDhallWithNormalizer (:+:)" declaredR++instance (GenericToDhall (f :*: g), GenericToDhall (h :*: i)) => GenericToDhall ((f :*: g) :*: (h :*: i)) where+    genericToDhallWithNormalizer inputNormalizer options = do+        Encoder embedL declaredL <- genericToDhallWithNormalizer inputNormalizer options+        Encoder embedR declaredR <- genericToDhallWithNormalizer inputNormalizer options++        let embed (l :*: r) =+                RecordLit (Dhall.Map.union mapL mapR)+              where+                mapL =+                    unsafeExpectRecordLit "genericToDhallWithNormalizer (:*:)" (embedL l)++                mapR =+                    unsafeExpectRecordLit "genericToDhallWithNormalizer (:*:)" (embedR r)++        let declared = Record (Dhall.Map.union mapL mapR)+              where+                mapL = unsafeExpectRecord "genericToDhallWithNormalizer (:*:)" declaredL+                mapR = unsafeExpectRecord "genericToDhallWithNormalizer (:*:)" declaredR++        pure (Encoder {..})++instance (GenericToDhall (f :*: g), Selector s, ToDhall a) => GenericToDhall ((f :*: g) :*: M1 S s (K1 i a)) where+    genericToDhallWithNormalizer inputNormalizer options@InterpretOptions{..} = do+        let nR :: M1 S s (K1 i a) r+            nR = undefined++        nameR <- fmap fieldModifier (getSelName nR)++        Encoder embedL declaredL <- genericToDhallWithNormalizer inputNormalizer options++        let Encoder embedR declaredR = injectWith inputNormalizer++        let embed (l :*: M1 (K1 r)) =+                RecordLit (Dhall.Map.insert nameR (Core.makeRecordField $ embedR r) mapL)+              where+                mapL =+                    unsafeExpectRecordLit "genericToDhallWithNormalizer (:*:)" (embedL l)++        let declared = Record (Dhall.Map.insert nameR (Core.makeRecordField declaredR) mapL)+              where+                mapL = unsafeExpectRecord "genericToDhallWithNormalizer (:*:)" declaredL++        return (Encoder {..})++instance (Selector s, ToDhall a, GenericToDhall (f :*: g)) => GenericToDhall (M1 S s (K1 i a) :*: (f :*: g)) where+    genericToDhallWithNormalizer inputNormalizer options@InterpretOptions{..} = do+        let nL :: M1 S s (K1 i a) r+            nL = undefined++        nameL <- fmap fieldModifier (getSelName nL)++        let Encoder embedL declaredL = injectWith inputNormalizer++        Encoder embedR declaredR <- genericToDhallWithNormalizer inputNormalizer options++        let embed (M1 (K1 l) :*: r) =+                RecordLit (Dhall.Map.insert nameL (Core.makeRecordField $ embedL l) mapR)+              where+                mapR =+                    unsafeExpectRecordLit "genericToDhallWithNormalizer (:*:)" (embedR r)++        let declared = Record (Dhall.Map.insert nameL (Core.makeRecordField declaredL) mapR)+              where+                mapR = unsafeExpectRecord "genericToDhallWithNormalizer (:*:)" declaredR++        return (Encoder {..})++instance (Selector s1, Selector s2, ToDhall a1, ToDhall a2) => GenericToDhall (M1 S s1 (K1 i1 a1) :*: M1 S s2 (K1 i2 a2)) where+    genericToDhallWithNormalizer inputNormalizer InterpretOptions{..} = do+        let nL :: M1 S s1 (K1 i1 a1) r+            nL = undefined++        let nR :: M1 S s2 (K1 i2 a2) r+            nR = undefined++        nameL <- fmap fieldModifier (getSelName nL)+        nameR <- fmap fieldModifier (getSelName nR)++        let Encoder embedL declaredL = injectWith inputNormalizer+        let Encoder embedR declaredR = injectWith inputNormalizer++        let embed (M1 (K1 l) :*: M1 (K1 r)) =+                RecordLit $+                    Dhall.Map.fromList+                        [ (nameL, Core.makeRecordField $ embedL l)+                        , (nameR, Core.makeRecordField $ embedR r) ]+++        let declared =+                Record $ Dhall.Map.fromList+                    [ (nameL, Core.makeRecordField declaredL)+                    , (nameR, Core.makeRecordField declaredR) ]+++        return (Encoder {..})++instance GenericToDhall U1 where+    genericToDhallWithNormalizer _ _ = pure (Encoder {..})+      where+        embed _ = RecordLit mempty++        declared = Record mempty++{-| Use the default options for injecting a value, whose structure is+determined generically.++This can be used when you want to use 'ToDhall' on types that you don't+want to define orphan instances for.+-}+genericToDhall+  :: (Generic a, GenericToDhall (Rep a)) => Encoder a+genericToDhall+    = genericToDhallWith defaultInterpretOptions++{-| Use custom options for injecting a value, whose structure is+determined generically.++This can be used when you want to use 'ToDhall' on types that you don't+want to define orphan instances for.+-}+genericToDhallWith+  :: (Generic a, GenericToDhall (Rep a)) => InterpretOptions -> Encoder a+genericToDhallWith options = genericToDhallWithInputNormalizer options defaultInputNormalizer++{-| `genericToDhallWithInputNormalizer` is like `genericToDhallWith`, but+    instead of using the `defaultInputNormalizer` it expects an custom+    `InputNormalizer`.+-}+genericToDhallWithInputNormalizer+  :: (Generic a, GenericToDhall (Rep a)) => InterpretOptions -> InputNormalizer -> Encoder a+genericToDhallWithInputNormalizer options inputNormalizer+    = contramap GHC.Generics.from (evalState (genericToDhallWithNormalizer inputNormalizer options) 1)++++{-| The 'RecordEncoder' divisible (contravariant) functor allows you to build+    an 'Encoder' for a Dhall record.++    For example, let's take the following Haskell data type:++>>> :{+data Project = Project+  { projectName :: Text+  , projectDescription :: Text+  , projectStars :: Natural+  }+:}++    And assume that we have the following Dhall record that we would like to+    parse as a @Project@:++> { name =+>     "dhall-haskell"+> , description =+>     "A configuration language guaranteed to terminate"+> , stars =+>     289+> }++    Our encoder has type 'Encoder' @Project@, but we can't build that out of any+    smaller encoders, as 'Encoder's cannot be combined (they are only 'Contravariant's).+    However, we can use an 'RecordEncoder' to build an 'Encoder' for @Project@:++>>> :{+injectProject :: Encoder Project+injectProject =+  recordEncoder+    ( adapt >$< encodeFieldWith "name" inject+            >*< encodeFieldWith "description" inject+            >*< encodeFieldWith "stars" inject+    )+  where+    adapt (Project{..}) = (projectName, (projectDescription, projectStars))+:}++    Or, since we are simply using the `ToDhall` instance to inject each field, we could write++>>> :{+injectProject :: Encoder Project+injectProject =+  recordEncoder+    ( adapt >$< encodeField "name"+            >*< encodeField "description"+            >*< encodeField "stars"+    )+  where+    adapt (Project{..}) = (projectName, (projectDescription, projectStars))+:}++-}+newtype RecordEncoder a+  = RecordEncoder (Dhall.Map.Map Text (Encoder a))++instance Contravariant RecordEncoder where+  contramap f (RecordEncoder encodeTypeRecord) = RecordEncoder $ contramap f <$> encodeTypeRecord++instance Divisible RecordEncoder where+  divide f (RecordEncoder bEncoderRecord) (RecordEncoder cEncoderRecord) =+      RecordEncoder+    $ Dhall.Map.union+      ((contramap $ fst . f) <$> bEncoderRecord)+      ((contramap $ snd . f) <$> cEncoderRecord)+  conquer = RecordEncoder mempty++-- | Convert a `RecordEncoder` into the equivalent `Encoder`.+recordEncoder :: RecordEncoder a -> Encoder a+recordEncoder (RecordEncoder encodeTypeRecord) = Encoder makeRecordLit recordType+  where+    recordType = Record $ (Core.makeRecordField . declared) <$> encodeTypeRecord+    makeRecordLit x = RecordLit $ (Core.makeRecordField . ($ x) . embed) <$> encodeTypeRecord++{-| Specify how to encode one field of a record using the default `ToDhall`+    instance for that type.+-}+encodeField :: ToDhall a => Text -> RecordEncoder a+encodeField name = encodeFieldWith name inject++{-| Specify how to encode one field of a record by supplying an explicit+    `Encoder` for that field.+-}+encodeFieldWith :: Text -> Encoder a -> RecordEncoder a+encodeFieldWith name encodeType = RecordEncoder $ Dhall.Map.singleton name encodeType++++{-| 'UnionEncoder' allows you to build an 'Encoder' for a Dhall record.++    For example, let's take the following Haskell data type:++>>> :{+data Status = Queued Natural+            | Result Text+            | Errored Text+:}++    And assume that we have the following Dhall union that we would like to+    parse as a @Status@:++> < Result : Text+> | Queued : Natural+> | Errored : Text+> >.Result "Finish successfully"++    Our encoder has type 'Encoder' @Status@, but we can't build that out of any+    smaller encoders, as 'Encoder's cannot be combined.+    However, we can use an 'UnionEncoder' to build an 'Encoder' for @Status@:++>>> :{+injectStatus :: Encoder Status+injectStatus = adapt >$< unionEncoder+  (   encodeConstructorWith "Queued"  inject+  >|< encodeConstructorWith "Result"  inject+  >|< encodeConstructorWith "Errored" inject+  )+  where+    adapt (Queued  n) = Left n+    adapt (Result  t) = Right (Left t)+    adapt (Errored e) = Right (Right e)+:}++    Or, since we are simply using the `ToDhall` instance to inject each branch, we could write++>>> :{+injectStatus :: Encoder Status+injectStatus = adapt >$< unionEncoder+  (   encodeConstructor "Queued"+  >|< encodeConstructor "Result"+  >|< encodeConstructor "Errored"+  )+  where+    adapt (Queued  n) = Left n+    adapt (Result  t) = Right (Left t)+    adapt (Errored e) = Right (Right e)+:}++-}+newtype UnionEncoder a =+  UnionEncoder+    ( Data.Functor.Product.Product+        ( Control.Applicative.Const+            ( Dhall.Map.Map+                Text+                ( Expr Src Void )+            )+        )+        ( Op (Text, Expr Src Void) )+        a+    )+  deriving (Contravariant)++-- | Convert a `UnionEncoder` into the equivalent `Encoder`.+unionEncoder :: UnionEncoder a -> Encoder a+unionEncoder ( UnionEncoder ( Data.Functor.Product.Pair ( Control.Applicative.Const fields ) ( Op embedF ) ) ) =+    Encoder+      { embed = \x ->+          let (name, y) = embedF x+          in  case notEmptyRecordLit y of+                  Nothing  -> Field (Union fields') $ Core.makeFieldSelection name+                  Just val -> App (Field (Union fields') $ Core.makeFieldSelection name) val+      , declared =+          Union fields'+      }+  where+    fields' = fmap notEmptyRecord fields++{-| Specify how to encode an alternative by using the default `ToDhall` instance+    for that type.+-}+encodeConstructor+    :: ToDhall a+    => Text+    -> UnionEncoder a+encodeConstructor name = encodeConstructorWith name inject++{-| Specify how to encode an alternative by providing an explicit `Encoder`+    for that alternative.+-}+encodeConstructorWith+    :: Text+    -> Encoder a+    -> UnionEncoder a+encodeConstructorWith name encodeType = UnionEncoder $+    Data.Functor.Product.Pair+      ( Control.Applicative.Const+          ( Dhall.Map.singleton+              name+              ( declared encodeType )+          )+      )+      ( Op ( (name,) . embed encodeType )+      )++-- | Combines two 'UnionEncoder' values.  See 'UnionEncoder' for usage+-- notes.+--+-- Ideally, this matches 'Data.Functor.Contravariant.Divisible.chosen';+-- however, this allows 'UnionEncoder' to not need a 'Divisible' instance+-- itself (since no instance is possible).+(>|<) :: UnionEncoder a -> UnionEncoder b -> UnionEncoder (Either a b)+UnionEncoder (Data.Functor.Product.Pair (Control.Applicative.Const mx) (Op fx))+    >|< UnionEncoder (Data.Functor.Product.Pair (Control.Applicative.Const my) (Op fy)) =+    UnionEncoder+      ( Data.Functor.Product.Pair+          ( Control.Applicative.Const (mx <> my) )+          ( Op (either fx fy) )+      )++infixr 5 >|<++++-- | Infix 'divided'+(>*<) :: Divisible f => f a -> f b -> f (a, b)+(>*<) = divided++infixr 5 >*<
+ src/Dhall/Marshal/Internal.hs view
@@ -0,0 +1,193 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ViewPatterns      #-}++{-| Please read the "Dhall.Tutorial" module, which contains a tutorial explaining+    how to use the language, the compiler, and this library+-}++module Dhall.Marshal.Internal+    ( InputNormalizer(..)+    , defaultInputNormalizer+    , InterpretOptions(..)+    , SingletonConstructors(..)+    , defaultInterpretOptions++    -- * Miscellaneous+    , Result(..)++    -- * Helpers for the generic deriving machinery+    , getSelName+    , notEmptyRecord+    , notEmptyRecordLit+    , unsafeExpectRecord+    , unsafeExpectRecordLit+    , unsafeExpectUnion+    , unsafeExpectUnionLit++    -- * Re-exports+    , Fix(..)+    , HashMap+    , Int8+    , Int16+    , Int32+    , Int64+    , Map+    , Natural+    , Scientific+    , Seq+    , Text+    , Vector+    , Void+    , Word8+    , Word16+    , Word32+    , Word64+    , Generic+    ) where++import Control.Monad.Trans.State.Strict+import Data.Fix                         (Fix (..))+import Data.HashMap.Strict              (HashMap)+import Data.Int                         (Int16, Int32, Int64, Int8)+import Data.Map                         (Map)+import Data.Scientific                  (Scientific)+import Data.Sequence                    (Seq)+import Data.Text                        (Text)+import Data.Vector                      (Vector)+import Data.Void                        (Void)+import Data.Word                        (Word16, Word32, Word64, Word8)+import Dhall.Parser                     (Src (..))+import Dhall.Syntax                     (Expr (..), RecordField (..))+import GHC.Generics+import Numeric.Natural                  (Natural)+import Prelude                          hiding (maybe, sequence)++import qualified Data.Text+import qualified Dhall.Core as Core+import qualified Dhall.Map++{-| This type is exactly the same as `Data.Fix.Fix` except with a different+    `Dhall.Marshal.Decode.FromDhall` instance.  This intermediate type+    simplifies the implementation of the inner loop for the+    `Dhall.Marshal.Decode.FromDhall` instance for `Fix`.+-}+newtype Result f = Result { _unResult :: f (Result f) }++{-| Use these options to tweak how Dhall derives a generic implementation of+    `Dhall.Marshal.Decode.FromDhall`.+-}+data InterpretOptions = InterpretOptions+    { fieldModifier       :: Text -> Text+    -- ^ Function used to transform Haskell field names into their corresponding+    --   Dhall field names+    , constructorModifier :: Text -> Text+    -- ^ Function used to transform Haskell constructor names into their+    --   corresponding Dhall alternative names+    , singletonConstructors :: SingletonConstructors+    -- ^ Specify how to handle constructors with only one field.  The default is+    --   `Smart`+    }++{-| This is only used by the `Dhall.Marshal.Decode.FromDhall` instance for+    functions in order to normalize the function input before marshaling the+    input into a Dhall expression.+-}+newtype InputNormalizer = InputNormalizer+  { getInputNormalizer :: Core.ReifiedNormalizer Void }++-- | Default normalization-related settings (no custom normalization)+defaultInputNormalizer :: InputNormalizer+defaultInputNormalizer = InputNormalizer+ { getInputNormalizer = Core.ReifiedNormalizer (const (pure Nothing)) }++{-| This type specifies how to model a Haskell constructor with 1 field in+    Dhall++    For example, consider the following Haskell datatype definition:++    > data Example = Foo { x :: Double } | Bar Double++    Depending on which option you pick, the corresponding Dhall type could be:++    > < Foo : Double | Bar : Double >                   -- Bare++    > < Foo : { x : Double } | Bar : { _1 : Double } >  -- Wrapped++    > < Foo : { x : Double } | Bar : Double >           -- Smart+-}+data SingletonConstructors+    = Bare+    -- ^ Never wrap the field in a record+    | Wrapped+    -- ^ Always wrap the field in a record+    | Smart+    -- ^ Only fields in a record if they are named++{-| Default interpret options for generics-based instances,+    which you can tweak or override, like this:++> genericAutoWith+>     (defaultInterpretOptions { fieldModifier = Data.Text.Lazy.dropWhile (== '_') })+-}+defaultInterpretOptions :: InterpretOptions+defaultInterpretOptions = InterpretOptions+    { fieldModifier =+          id+    , constructorModifier =+          id+    , singletonConstructors =+          Smart+    }++unsafeExpectUnion+    :: Text -> Expr Src Void -> Dhall.Map.Map Text (Maybe (Expr Src Void))+unsafeExpectUnion _ (Union kts) =+    kts+unsafeExpectUnion name expression =+    Core.internalError+        (name <> ": Unexpected constructor: " <> Core.pretty expression)++unsafeExpectRecord+    :: Text -> Expr Src Void -> Dhall.Map.Map Text (RecordField Src Void)+unsafeExpectRecord _ (Record kts) =+    kts+unsafeExpectRecord name expression =+    Core.internalError+        (name <> ": Unexpected constructor: " <> Core.pretty expression)++unsafeExpectUnionLit+    :: Text+    -> Expr Src Void+    -> (Text, Maybe (Expr Src Void))+unsafeExpectUnionLit _ (Field (Union _) (Core.fieldSelectionLabel -> k)) =+    (k, Nothing)+unsafeExpectUnionLit _ (App (Field (Union _) (Core.fieldSelectionLabel -> k)) v) =+    (k, Just v)+unsafeExpectUnionLit name expression =+    Core.internalError+        (name <> ": Unexpected constructor: " <> Core.pretty expression)++unsafeExpectRecordLit+    :: Text -> Expr Src Void -> Dhall.Map.Map Text (RecordField Src Void)+unsafeExpectRecordLit _ (RecordLit kvs) =+    kvs+unsafeExpectRecordLit name expression =+    Core.internalError+        (name <> ": Unexpected constructor: " <> Core.pretty expression)++notEmptyRecordLit :: Expr s a -> Maybe (Expr s a)+notEmptyRecordLit e = case e of+    RecordLit m | null m -> Nothing+    _                    -> Just e++notEmptyRecord :: Expr s a -> Maybe (Expr s a)+notEmptyRecord e = case e of+    Record m | null m -> Nothing+    _                 -> Just e++getSelName :: Selector s => M1 i s f a -> State Int Text+getSelName n = case selName n of+    "" -> do i <- get+             put (i + 1)+             pure (Data.Text.pack ("_" ++ show i))+    nn -> pure (Data.Text.pack nn)
+ src/Dhall/Normalize.hs view
@@ -0,0 +1,1037 @@+{-# LANGUAGE BangPatterns      #-}+{-# LANGUAGE LambdaCase        #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes        #-}+{-# LANGUAGE ViewPatterns      #-}++module Dhall.Normalize (+      alphaNormalize+    , normalize+    , normalizeWith+    , normalizeWithM+    , Normalizer+    , NormalizerM+    , ReifiedNormalizer (..)+    , judgmentallyEqual+    , subst+    , Syntax.shift+    , isNormalized+    , isNormalizedWith+    , freeIn+    ) where++import Control.Applicative   (empty)+import Data.Foldable+import Data.Functor.Identity (Identity (..))+import Data.List.NonEmpty    (NonEmpty (..))+import Data.Sequence         (ViewL (..), ViewR (..))+import Data.Traversable+import Instances.TH.Lift     ()+import Prelude               hiding (succ)++import Dhall.Syntax+    ( Binding (Binding)+    , Chunks (..)+    , DhallDouble (..)+    , Expr (..)+    , FieldSelection (..)+    , FunctionBinding (..)+    , PreferAnnotation (..)+    , RecordField (..)+    , Var (..)+    , WithComponent (..)+    )++import qualified Data.Sequence+import qualified Data.Set+import qualified Data.Text     as Text+import qualified Dhall.Eval    as Eval+import qualified Dhall.Map+import qualified Dhall.Syntax  as Syntax+import qualified Lens.Micro    as Lens++{-| Returns `True` if two expressions are α-equivalent and β-equivalent and+    `False` otherwise++    `judgmentallyEqual` can fail with an `error` if you compare ill-typed+    expressions+-}+judgmentallyEqual :: Eq a => Expr s a -> Expr t a -> Bool+judgmentallyEqual = Eval.judgmentallyEqual+{-# INLINE judgmentallyEqual #-}++{-| Substitute all occurrences of a variable with an expression++> subst x C B  ~  B[x := C]+-}+subst :: Var -> Expr s a -> Expr s a -> Expr s a+subst _ _ (Const a) = Const a+subst (V x n) e (Lam cs (FunctionBinding src0 y src1 src2 _A) b) =+    Lam cs (FunctionBinding src0 y src1 src2 _A') b'+  where+    _A' = subst (V x n )                         e  _A+    b'  = subst (V x n') (Syntax.shift 1 (V y 0) e)  b+    n'  = if x == y then n + 1 else n+subst (V x n) e (Pi cs y _A _B) = Pi cs y _A' _B'+  where+    _A' = subst (V x n )                         e  _A+    _B' = subst (V x n') (Syntax.shift 1 (V y 0) e) _B+    n'  = if x == y then n + 1 else n+subst v e (Var v') = if v == v' then e else Var v'+subst (V x n) e (Let (Binding src0 f src1 mt src2 r) b) =+    Let (Binding src0 f src1 mt' src2 r') b'+  where+    b' = subst (V x n') (Syntax.shift 1 (V f 0) e) b+      where+        n' = if x == f then n + 1 else n++    mt' = fmap (fmap (subst (V x n) e)) mt+    r'  =             subst (V x n) e  r+subst x e expression = Lens.over Syntax.subExpressions (subst x e) expression++{-| This function is used to determine whether folds like @Natural/fold@ or+    @List/fold@ should be lazy or strict in their accumulator based on the type+    of the accumulator++    If this function returns `True`, then they will be strict in their+    accumulator since we can guarantee an upper bound on the amount of work to+    normalize the accumulator on each step of the loop.  If this function+    returns `False` then they will be lazy in their accumulator and only+    normalize the final result at the end of the fold+-}+boundedType :: Expr s a -> Bool+boundedType Bool             = True+boundedType Natural          = True+boundedType Integer          = True+boundedType Double           = True+boundedType Text             = True+boundedType (App List _)     = False+boundedType (App Optional t) = boundedType t+boundedType (Record kvs)     = all (boundedType . recordFieldValue) kvs+boundedType (Union kvs)      = all (all boundedType) kvs+boundedType _                = False++{-| α-normalize an expression by renaming all bound variables to @\"_\"@ and+    using De Bruijn indices to distinguish them++>>> mfb = Syntax.makeFunctionBinding+>>> alphaNormalize (Lam mempty (mfb "a" (Const Type)) (Lam mempty (mfb "b" (Const Type)) (Lam mempty (mfb "x" "a") (Lam mempty (mfb "y" "b") "x"))))+Lam Nothing (FunctionBinding {functionBindingSrc0 = Nothing, functionBindingVariable = "_", functionBindingSrc1 = Nothing, functionBindingSrc2 = Nothing, functionBindingAnnotation = Const Type}) (Lam Nothing (FunctionBinding {functionBindingSrc0 = Nothing, functionBindingVariable = "_", functionBindingSrc1 = Nothing, functionBindingSrc2 = Nothing, functionBindingAnnotation = Const Type}) (Lam Nothing (FunctionBinding {functionBindingSrc0 = Nothing, functionBindingVariable = "_", functionBindingSrc1 = Nothing, functionBindingSrc2 = Nothing, functionBindingAnnotation = Var (V "_" 1)}) (Lam Nothing (FunctionBinding {functionBindingSrc0 = Nothing, functionBindingVariable = "_", functionBindingSrc1 = Nothing, functionBindingSrc2 = Nothing, functionBindingAnnotation = Var (V "_" 1)}) (Var (V "_" 1)))))++    α-normalization does not affect free variables:++>>> alphaNormalize "x"+Var (V "x" 0)++-}+alphaNormalize :: Expr s a -> Expr s a+alphaNormalize = Eval.alphaNormalize+{-# INLINE alphaNormalize #-}++{-| Reduce an expression to its normal form, performing beta reduction++    `normalize` does not type-check the expression.  You may want to type-check+    expressions before normalizing them since normalization can convert an+    ill-typed expression into a well-typed expression.++    `normalize` can also fail with `error` if you normalize an ill-typed+    expression+-}+normalize :: Eq a => Expr s a -> Expr t a+normalize = Eval.normalize+{-# INLINE normalize #-}++{-| Reduce an expression to its normal form, performing beta reduction and applying+    any custom definitions.++    `normalizeWith` is designed to be used with function `Dhall.TypeCheck.typeWith`. The `Dhall.TypeCheck.typeWith`+    function allows typing of Dhall functions in a custom typing context whereas+    `normalizeWith` allows evaluating Dhall expressions in a custom context.++    To be more precise `normalizeWith` applies the given normalizer when it finds an+    application term that it cannot reduce by other means.++    Note that the context used in normalization will determine the properties of normalization.+    That is, if the functions in custom context are not total then the Dhall language, evaluated+    with those functions is not total either.++    `normalizeWith` can fail with an `error` if you normalize an ill-typed+    expression+-}+normalizeWith :: Eq a => Maybe (ReifiedNormalizer a) -> Expr s a -> Expr t a+normalizeWith (Just ctx) t = runIdentity (normalizeWithM (getReifiedNormalizer ctx) t)+normalizeWith _          t = Eval.normalize t+{-# INLINABLE normalizeWith #-}++{-| This function generalizes `normalizeWith` by allowing the custom normalizer+    to use an arbitrary `Monad`++    `normalizeWithM` can fail with an `error` if you normalize an ill-typed+    expression+-}+normalizeWithM+    :: (Monad m, Eq a) => NormalizerM m a -> Expr s a -> m (Expr t a)+normalizeWithM ctx e0 = loop (Syntax.denote e0)+ where+  loop e = ctx e >>= \case+      Just e' -> loop e'+      Nothing -> case e of+          Const k -> pure (Const k)+          Var v -> pure (Var v)+          Lam cs (FunctionBinding { functionBindingVariable = x, functionBindingAnnotation = _A }) b ->+              Lam cs <$> (Syntax.makeFunctionBinding x <$> _A') <*> b'+            where+              _A' = loop _A+              b'  = loop b+          Pi cs x _A _B -> Pi cs x <$> _A' <*> _B'+            where+              _A' = loop _A+              _B' = loop _B+          App f a -> do+              f' <- loop f+              a' <- loop a+              case f' of+                Lam _ (FunctionBinding _ x _ _ _A) b₀ -> do++                    let a₂ = Syntax.shift 1 (V x 0) a'+                    let b₁ = subst (V x 0) a₂ b₀+                    let b₂ = Syntax.shift (-1) (V x 0) b₁++                    loop b₂+                _ ->+                  case App f' a' of+                    App (App (App (App NaturalFold (NaturalLit n0)) t) succ') zero -> do+                      t' <- loop t+                      if boundedType t' then strict else lazy+                      where+                        -- Use an `Integer` for the loop, due to the following+                        -- issue:+                        --+                        -- https://github.com/ghcjs/ghcjs/issues/782+                        strict =       strictLoop (fromIntegral n0 :: Integer)+                        lazy   = loop (  lazyLoop (fromIntegral n0 :: Integer))++                        strictLoop !n = do+                            z <- loop zero+                            strictLoopShortcut n z++                        strictLoopShortcut 0 !previous = pure previous+                        strictLoopShortcut !n !previous = do+                            current <- loop (App succ' previous)+                            if judgmentallyEqual previous current+                                then pure previous+                                else strictLoopShortcut (n - 1) current++                        lazyLoop 0 = zero+                        lazyLoop !n = App succ' (lazyLoop (n - 1))+                    App NaturalBuild g -> loop (App (App (App g Natural) succ) zero)+                      where+                        succ = Lam mempty (Syntax.makeFunctionBinding "n" Natural) (NaturalPlus "n" (NaturalLit 1))++                        zero = NaturalLit 0+                    App NaturalIsZero (NaturalLit n) -> pure (BoolLit (n == 0))+                    App NaturalEven (NaturalLit n) -> pure (BoolLit (even n))+                    App NaturalOdd (NaturalLit n) -> pure (BoolLit (odd n))+                    App NaturalToInteger (NaturalLit n) -> pure (IntegerLit (toInteger n))+                    App NaturalShow (NaturalLit n) ->+                        pure (TextLit (Chunks [] (Text.pack (show n))))+                    App (App NaturalSubtract (NaturalLit x)) (NaturalLit y)+                        -- Use an `Integer` for the subtraction, due to the+                        -- following issue:+                        --+                        -- https://github.com/ghcjs/ghcjs/issues/782+                        | y >= x ->+                            pure (NaturalLit (fromIntegral (subtract (fromIntegral x :: Integer) (fromIntegral y :: Integer))))+                        | otherwise ->+                            pure (NaturalLit 0)+                    App (App NaturalSubtract (NaturalLit 0)) y -> pure y+                    App (App NaturalSubtract _) (NaturalLit 0) -> pure (NaturalLit 0)+                    App (App NaturalSubtract x) y | Eval.judgmentallyEqual x y -> pure (NaturalLit 0)+                    App IntegerClamp (IntegerLit n)+                        | 0 <= n -> pure (NaturalLit (fromInteger n))+                        | otherwise -> pure (NaturalLit 0)+                    App IntegerNegate (IntegerLit n) ->+                        pure (IntegerLit (negate n))+                    App IntegerShow (IntegerLit n)+                        | 0 <= n    -> pure (TextLit (Chunks [] ("+" <> Text.pack (show n))))+                        | otherwise -> pure (TextLit (Chunks [] (Text.pack (show n))))+                    -- `(read . show)` is used instead of `fromInteger` because `read` uses+                    -- the correct rounding rule.+                    -- See https://gitlab.haskell.org/ghc/ghc/issues/17231.+                    App IntegerToDouble (IntegerLit n) -> pure (DoubleLit ((DhallDouble . read . show) n))+                    App DoubleShow (DoubleLit (DhallDouble n)) ->+                        pure (TextLit (Chunks [] (Text.pack (show n))))+                    App (App ListBuild _A₀) g -> loop (App (App (App g list) cons) nil)+                      where+                        _A₁ = Syntax.shift 1 "a" _A₀++                        list = App List _A₀++                        cons =+                            Lam mempty (Syntax.makeFunctionBinding "a" _A₀)+                                (Lam mempty+                                    (Syntax.makeFunctionBinding "as" (App List _A₁))+                                    (ListAppend (ListLit Nothing (pure "a")) "as")+                                )++                        nil = ListLit (Just (App List _A₀)) empty+                    App (App (App (App (App ListFold _) (ListLit _ xs)) t) cons) nil -> do+                      t' <- loop t+                      if boundedType t' then strict else lazy+                      where+                        strict =       foldr strictCons strictNil xs+                        lazy   = loop (foldr   lazyCons   lazyNil xs)++                        strictNil = loop nil+                        lazyNil   =      nil++                        strictCons y ys =+                          App (App cons y) <$> ys >>= loop+                        lazyCons   y ys =       App (App cons y) ys+                    App (App ListLength _) (ListLit _ ys) ->+                        pure (NaturalLit (fromIntegral (Data.Sequence.length ys)))+                    App (App ListHead t) (ListLit _ ys) -> loop o+                      where+                        o = case Data.Sequence.viewl ys of+                                y :< _ -> Some y+                                _      -> App None t+                    App (App ListLast t) (ListLit _ ys) -> loop o+                      where+                        o = case Data.Sequence.viewr ys of+                                _ :> y -> Some y+                                _      -> App None t+                    App (App ListIndexed _A₀) (ListLit _ as₀) -> loop (ListLit t as₁)+                      where+                        as₁ = Data.Sequence.mapWithIndex adapt as₀++                        _A₂ = Record (Dhall.Map.fromList kts)+                          where+                            kts = [ ("index", Syntax.makeRecordField Natural)+                                  , ("value", Syntax.makeRecordField _A₀)+                                  ]++                        t | null as₀  = Just (App List _A₂)+                          | otherwise = Nothing++                        adapt n a_ =+                            RecordLit (Dhall.Map.fromList kvs)+                          where+                            kvs = [ ("index", Syntax.makeRecordField $ NaturalLit (fromIntegral n))+                                  , ("value", Syntax.makeRecordField a_)+                                  ]+                    App (App ListReverse _) (ListLit t xs) ->+                        loop (ListLit t (Data.Sequence.reverse xs))+                    App TextShow (TextLit (Chunks [] oldText)) ->+                        loop (TextLit (Chunks [] newText))+                      where+                        newText = Eval.textShow oldText+                    App+                        (App (App TextReplace (TextLit (Chunks [] ""))) _)+                        haystack ->+                            return haystack+                    App (App+                            (App TextReplace (TextLit (Chunks [] needleText)))+                            (TextLit (Chunks [] replacementText))+                        )+                        (TextLit (Chunks xys z)) -> do+                            let xys' = do+                                    (x, y) <- xys++                                    let x' = Text.replace needleText replacementText x+                                    return (x', y)++                            let z' = Text.replace needleText replacementText z++                            return (TextLit (Chunks xys' z'))+                    App (App+                            (App TextReplace (TextLit (Chunks [] needleText)))+                            replacement+                        )+                        (TextLit (Chunks [] lastText)) -> do+                            let (prefix, suffix) =+                                    Text.breakOn needleText lastText++                            if Text.null suffix+                                then return (TextLit (Chunks [] lastText))+                                else do+                                    let remainder =+                                            Text.drop+                                                (Text.length needleText)+                                                suffix++                                    loop (TextAppend (TextLit (Chunks [(prefix, replacement)] "")) (App (App (App TextReplace (TextLit (Chunks [] needleText))) replacement) (TextLit (Chunks [] remainder))))+                    App (App+                            (App TextReplace (TextLit (Chunks [] needleText)))+                            replacement+                        )+                        (TextLit+                            (Chunks+                                ((firstText, firstInterpolation) : chunks)+                                lastText+                            )+                        ) -> do+                            let (prefix, suffix) =+                                    Text.breakOn needleText firstText++                            if Text.null suffix+                                then do+                                    loop (TextAppend (TextLit (Chunks [(firstText, firstInterpolation)] "")) (App (App (App TextReplace (TextLit (Chunks [] needleText))) replacement) (TextLit (Chunks chunks lastText))))+                                else do+                                    let remainder =+                                            Text.drop+                                                (Text.length needleText)+                                                suffix++                                    loop (TextAppend (TextLit (Chunks [(prefix, replacement)] "")) (App (App (App TextReplace (TextLit (Chunks [] needleText))) replacement) (TextLit (Chunks ((remainder, firstInterpolation) : chunks) lastText))))+                    App DateShow (DateLiteral date) ->+                        loop (TextLit (Chunks [] text))+                      where+                        text = Eval.dateShow date+                    App TimeShow (TimeLiteral time precision) ->+                        loop (TextLit (Chunks [] text))+                      where+                        text = Eval.timeShow time precision+                    App TimeZoneShow (TimeZoneLiteral timezone) ->+                        loop (TextLit (Chunks [] text))+                      where+                        text = Eval.timezoneShow timezone+                    _ -> do+                        res2 <- ctx (App f' a')+                        case res2 of+                            Nothing -> pure (App f' a')+                            Just app' -> loop app'+          Let (Binding _ f _ _ _ r) b -> loop b''+            where+              r'  = Syntax.shift   1  (V f 0) r+              b'  = subst (V f 0) r' b+              b'' = Syntax.shift (-1) (V f 0) b'+          Annot x _ -> loop x+          Bool -> pure Bool+          BoolLit b -> pure (BoolLit b)+          BoolAnd x y -> decide <$> loop x <*> loop y+            where+              decide (BoolLit True )  r              = r+              decide (BoolLit False)  _              = BoolLit False+              decide  l              (BoolLit True ) = l+              decide  _              (BoolLit False) = BoolLit False+              decide  l               r+                  | Eval.judgmentallyEqual l r = l+                  | otherwise                  = BoolAnd l r+          BoolOr x y -> decide <$> loop x <*> loop y+            where+              decide (BoolLit False)  r              = r+              decide (BoolLit True )  _              = BoolLit True+              decide  l              (BoolLit False) = l+              decide  _              (BoolLit True ) = BoolLit True+              decide  l               r+                  | Eval.judgmentallyEqual l r = l+                  | otherwise                  = BoolOr l r+          BoolEQ x y -> decide <$> loop x <*> loop y+            where+              decide (BoolLit True )  r              = r+              decide  l              (BoolLit True ) = l+              decide  l               r+                  | Eval.judgmentallyEqual l r = BoolLit True+                  | otherwise                  = BoolEQ l r+          BoolNE x y -> decide <$> loop x <*> loop y+            where+              decide (BoolLit False)  r              = r+              decide  l              (BoolLit False) = l+              decide  l               r+                  | Eval.judgmentallyEqual l r = BoolLit False+                  | otherwise                  = BoolNE l r+          BoolIf bool true false -> decide <$> loop bool <*> loop true <*> loop false+            where+              decide (BoolLit True )  l              _              = l+              decide (BoolLit False)  _              r              = r+              decide  b              (BoolLit True) (BoolLit False) = b+              decide  b               l              r+                  | Eval.judgmentallyEqual l r = l+                  | otherwise                  = BoolIf b l r+          Bytes -> pure Bytes+          BytesLit b -> pure (BytesLit b)+          Natural -> pure Natural+          NaturalLit n -> pure (NaturalLit n)+          NaturalFold -> pure NaturalFold+          NaturalBuild -> pure NaturalBuild+          NaturalIsZero -> pure NaturalIsZero+          NaturalEven -> pure NaturalEven+          NaturalOdd -> pure NaturalOdd+          NaturalToInteger -> pure NaturalToInteger+          NaturalShow -> pure NaturalShow+          NaturalSubtract -> pure NaturalSubtract+          NaturalPlus x y -> decide <$> loop x <*> loop y+            where+              decide (NaturalLit 0)  r             = r+              decide  l             (NaturalLit 0) = l+              decide (NaturalLit m) (NaturalLit n) = NaturalLit (m + n)+              decide  l              r             = NaturalPlus l r+          NaturalTimes x y -> decide <$> loop x <*> loop y+            where+              decide (NaturalLit 1)  r             = r+              decide  l             (NaturalLit 1) = l+              decide (NaturalLit 0)  _             = NaturalLit 0+              decide  _             (NaturalLit 0) = NaturalLit 0+              decide (NaturalLit m) (NaturalLit n) = NaturalLit (m * n)+              decide  l              r             = NaturalTimes l r+          Integer -> pure Integer+          IntegerLit n -> pure (IntegerLit n)+          IntegerClamp -> pure IntegerClamp+          IntegerNegate -> pure IntegerNegate+          IntegerShow -> pure IntegerShow+          IntegerToDouble -> pure IntegerToDouble+          Double -> pure Double+          DoubleLit n -> pure (DoubleLit n)+          DoubleShow -> pure DoubleShow+          Text -> pure Text+          TextLit (Chunks xys z) -> do+              chunks' <- mconcat <$> chunks+              case chunks' of+                  Chunks [("", x)] "" -> pure x+                  c                   -> pure (TextLit c)+            where+              chunks =+                ((++ [Chunks [] z]) . concat) <$> traverse process xys++              process (x, y) = do+                y' <- loop y+                case y' of+                  TextLit c -> pure [Chunks [] x, c]+                  _         -> pure [Chunks [(x, y')] mempty]+          TextAppend x y -> loop (TextLit (Chunks [("", x), ("", y)] ""))+          TextReplace -> pure TextReplace+          TextShow -> pure TextShow+          Date -> pure Date+          DateLiteral d -> pure (DateLiteral d)+          DateShow -> pure DateShow+          Time -> pure Time+          TimeLiteral t p -> pure (TimeLiteral t p)+          TimeShow -> pure TimeShow+          TimeZone -> pure TimeZone+          TimeZoneLiteral z -> pure (TimeZoneLiteral z)+          TimeZoneShow -> pure TimeZoneShow+          List -> pure List+          ListLit t es+              | Data.Sequence.null es -> ListLit <$> t' <*> pure Data.Sequence.empty+              | otherwise             -> ListLit Nothing <$> es'+            where+              t'  = traverse loop t+              es' = traverse loop es+          ListAppend x y -> decide <$> loop x <*> loop y+            where+              decide (ListLit _ m)  r            | Data.Sequence.null m = r+              decide  l            (ListLit _ n) | Data.Sequence.null n = l+              decide (ListLit t m) (ListLit _ n)                        = ListLit t (m <> n)+              decide  l             r                                   = ListAppend l r+          ListBuild -> pure ListBuild+          ListFold -> pure ListFold+          ListLength -> pure ListLength+          ListHead -> pure ListHead+          ListLast -> pure ListLast+          ListIndexed -> pure ListIndexed+          ListReverse -> pure ListReverse+          Optional -> pure Optional+          Some a -> Some <$> a'+            where+              a' = loop a+          None -> pure None+          Record kts -> Record . Dhall.Map.sort <$> kts'+            where+              f (RecordField s0 expr s1 s2) = (\expr' -> RecordField s0 expr' s1 s2) <$> loop expr+              kts' = traverse f kts+          RecordLit kvs -> RecordLit . Dhall.Map.sort <$> kvs'+            where+              f (RecordField s0 expr s1 s2) = (\expr' -> RecordField s0 expr' s1 s2) <$> loop expr+              kvs' = traverse f kvs+          Union kts -> Union . Dhall.Map.sort <$> kts'+            where+              kts' = traverse (traverse loop) kts+          Combine cs mk x y -> decide <$> loop x <*> loop y+            where+              decide (RecordLit m) r | Data.Foldable.null m =+                  r+              decide l (RecordLit n) | Data.Foldable.null n =+                  l+              decide (RecordLit m) (RecordLit n) =+                  RecordLit (Dhall.Map.unionWith f m n)+                where+                  f (RecordField _ expr _ _) (RecordField _ expr' _ _) =+                    Syntax.makeRecordField $ decide expr expr'+              decide l r =+                  Combine cs mk l r+          CombineTypes cs x y -> decide <$> loop x <*> loop y+            where+              decide (Record m) r | Data.Foldable.null m =+                  r+              decide l (Record n) | Data.Foldable.null n =+                  l+              decide (Record m) (Record n) =+                  Record (Dhall.Map.unionWith f m n)+                where+                  f (RecordField _ expr _ _) (RecordField _ expr' _ _) =+                    Syntax.makeRecordField $ decide expr expr'+              decide l r =+                  CombineTypes cs l r+          Prefer cs _ x y -> decide <$> loop x <*> loop y+            where+              decide (RecordLit m) r | Data.Foldable.null m =+                  r+              decide l (RecordLit n) | Data.Foldable.null n =+                  l+              decide (RecordLit m) (RecordLit n) =+                  RecordLit (Dhall.Map.union n m)+              decide l r | Eval.judgmentallyEqual l r =+                  l+              decide l r =+                  Prefer cs PreferFromSource l r+          RecordCompletion x y ->+              loop (Annot (Prefer mempty PreferFromCompletion (Field x def) y) (Field x typ))+            where+              def = Syntax.makeFieldSelection "default"+              typ = Syntax.makeFieldSelection "Type"+          Merge x y t      -> do+              x' <- loop x+              y' <- loop y+              case x' of+                  RecordLit kvsX ->+                      case y' of+                          Field (Union ktsY) (Syntax.fieldSelectionLabel -> kY) ->+                              case Dhall.Map.lookup kY ktsY of+                                  Just Nothing ->+                                      case recordFieldValue <$> Dhall.Map.lookup kY kvsX of+                                          Just vX -> return vX+                                          Nothing -> Merge x' y' <$> t'+                                  _ ->+                                      Merge x' y' <$> t'+                          App (Field (Union ktsY) (Syntax.fieldSelectionLabel -> kY)) vY ->+                              case Dhall.Map.lookup kY ktsY of+                                  Just (Just _) ->+                                      case recordFieldValue <$> Dhall.Map.lookup kY kvsX of+                                          Just vX -> loop (App vX vY)+                                          Nothing -> Merge x' y' <$> t'+                                  _ ->+                                      Merge x' y' <$> t'+                          Some a ->+                              case recordFieldValue <$> Dhall.Map.lookup "Some" kvsX of+                                  Just vX -> loop (App vX a)+                                  Nothing -> Merge x' y' <$> t'+                          App None _ ->+                              case recordFieldValue <$> Dhall.Map.lookup "None" kvsX of+                                  Just vX -> return vX+                                  Nothing -> Merge x' y' <$> t'+                          _ -> Merge x' y' <$> t'+                  _ -> Merge x' y' <$> t'+            where+              t' = traverse loop t+          ToMap x t        -> do+              x' <- loop x+              t' <- traverse loop t+              case x' of+                  RecordLit kvsX -> do+                      let entry (key, value) =+                              RecordLit+                                  (Dhall.Map.fromList+                                      [ ("mapKey"  , Syntax.makeRecordField $ TextLit (Chunks [] key))+                                      , ("mapValue", Syntax.makeRecordField value                  )+                                      ]+                                  )++                      let keyValues = Data.Sequence.fromList (map entry (Dhall.Map.toList $ recordFieldValue <$> kvsX))++                      let listType = case t' of+                              Just _ | null keyValues ->+                                  t'+                              _ ->+                                  Nothing++                      return (ListLit listType keyValues)+                  _ ->+                      return (ToMap x' t')+          ShowConstructor x -> do+              x' <- loop x+              return $ case x' of+                  Field (Union ktsY) (Syntax.fieldSelectionLabel -> kY) ->+                      case Dhall.Map.lookup kY ktsY of+                          Just Nothing -> TextLit (Chunks [] kY)+                          _ -> ShowConstructor x'+                  App (Field (Union ktsY) (Syntax.fieldSelectionLabel -> kY)) _ ->+                      case Dhall.Map.lookup kY ktsY of+                          Just (Just _) -> TextLit (Chunks [] kY)+                          _ -> ShowConstructor x'+                  Some _ ->+                      TextLit (Chunks [] "Some")+                  App None _ ->+                      TextLit (Chunks [] "None")+                  _ -> ShowConstructor x'+          Field r k@FieldSelection{fieldSelectionLabel = x}        -> do+              let singletonRecordLit v = RecordLit (Dhall.Map.singleton x v)++              r' <- loop r+              case r' of+                  RecordLit kvs ->+                      case Dhall.Map.lookup x kvs of+                          Just v  -> pure $ recordFieldValue v+                          Nothing -> Field <$> (RecordLit <$> traverse (Syntax.recordFieldExprs loop) kvs) <*> pure k+                  Project r_ _ -> loop (Field r_ k)+                  Prefer cs _ (RecordLit kvs) r_ -> case Dhall.Map.lookup x kvs of+                      Just v -> pure (Field (Prefer cs PreferFromSource (singletonRecordLit v) r_) k)+                      Nothing -> loop (Field r_ k)+                  Prefer _ _ l (RecordLit kvs) -> case Dhall.Map.lookup x kvs of+                      Just v -> pure $ recordFieldValue v+                      Nothing -> loop (Field l k)+                  Combine cs m (RecordLit kvs) r_ -> case Dhall.Map.lookup x kvs of+                      Just v -> pure (Field (Combine cs m (singletonRecordLit v) r_) k)+                      Nothing -> loop (Field r_ k)+                  Combine cs m l (RecordLit kvs) -> case Dhall.Map.lookup x kvs of+                      Just v -> pure (Field (Combine cs m l (singletonRecordLit v)) k)+                      Nothing -> loop (Field l k)+                  _ -> pure (Field r' k)+          Project x (Left fields)-> do+              x' <- loop x+              let fieldsSet = Data.Set.fromList fields+              case x' of+                  RecordLit kvs ->+                      pure (RecordLit (Dhall.Map.restrictKeys kvs fieldsSet))+                  Project y _ ->+                      loop (Project y (Left fields))+                  Prefer cs _ l (RecordLit rKvs) -> do+                      let rKs = Dhall.Map.keysSet rKvs+                      let l' = Project l (Left (Data.Set.toList (Data.Set.difference fieldsSet rKs)))+                      let r' = RecordLit (Dhall.Map.restrictKeys rKvs fieldsSet)+                      loop (Prefer cs PreferFromSource l' r')+                  _ | null fields -> pure (RecordLit mempty)+                    | otherwise   -> pure (Project x' (Left (Data.Set.toList (Data.Set.fromList fields))))+          Project r (Right e1) -> do+              e2 <- loop e1++              case e2 of+                  Record kts ->+                      loop (Project r (Left (Data.Set.toList (Dhall.Map.keysSet kts))))+                  _ -> do+                      r' <- loop r+                      pure (Project r' (Right e2))+          Assert t -> do+              t' <- loop t++              pure (Assert t')+          Equivalent cs l r -> do+              l' <- loop l+              r' <- loop r++              pure (Equivalent cs l' r')+          With r ks v -> do+              r' <- loop r+              v' <- loop v++              case r' of+                  RecordLit kvs ->+                      case ks of+                          WithLabel k :| [] ->+                              return (RecordLit (Dhall.Map.insert k (Syntax.makeRecordField v') kvs))+                          WithLabel k₀ :| k₁ : ks' -> do+                              let e₁ =+                                      case Dhall.Map.lookup k₀ kvs of+                                          Nothing  -> RecordLit mempty+                                          Just val -> Syntax.recordFieldValue val++                              e₂ <- loop (With e₁ (k₁ :| ks') v')++                              return (RecordLit (Dhall.Map.insert k₀ (Syntax.makeRecordField e₂) kvs))+                          WithQuestion :| _ -> do+                              return (With r' ks v')+                  Some t ->+                      case ks of+                          WithQuestion :| [] -> do+                              return (Some v')+                          WithQuestion :| k : ks' -> do+                              w <- loop (With t (k :| ks') v)+                              return (Some w)+                          WithLabel _ :| _ ->+                              return (With r' ks v')+                  App None _T ->+                      case ks of+                          WithQuestion :| _ ->+                              return (App None _T)+                          WithLabel _ :| _ ->+                              return (With r' ks v')+                  _ ->+                      return (With r' ks v')+          Note _ e' -> loop e'+          ImportAlt l _r -> loop l+          Embed a -> pure (Embed a)++-- | Use this to wrap you embedded functions (see `normalizeWith`) to make them+--   polymorphic enough to be used.+type NormalizerM m a = forall s. Expr s a -> m (Maybe (Expr s a))++-- | An variation on `NormalizerM` for pure normalizers+type Normalizer a = NormalizerM Identity a++-- | A reified 'Normalizer', which can be stored in structures without+-- running into impredicative polymorphism.+newtype ReifiedNormalizer a = ReifiedNormalizer+  { getReifiedNormalizer :: Normalizer a }++-- | Check if an expression is in a normal form given a context of evaluation.+--   Unlike `isNormalized`, this will fully normalize and traverse through the expression.+--+--   It is much more efficient to use `isNormalized`.+--+--  `isNormalizedWith` can fail with an `error` if you check an ill-typed+--  expression+isNormalizedWith :: (Eq s, Eq a) => Normalizer a -> Expr s a -> Bool+isNormalizedWith ctx e = e == normalizeWith (Just (ReifiedNormalizer ctx)) e++-- | Quickly check if an expression is in normal form+--+-- Given a well-typed expression @e@, @'isNormalized' e@ is equivalent to+-- @e == 'normalize' e@.+--+-- Given an ill-typed expression, 'isNormalized' may fail with an error, or+-- evaluate to either False or True!+isNormalized :: Eq a => Expr s a -> Bool+isNormalized e0 = loop (Syntax.denote e0)+  where+    loop e = case e of+      Const _ -> True+      Var _ -> True+      Lam _ (FunctionBinding Nothing _ Nothing Nothing a) b -> loop a && loop b+      Lam _ _ _ -> False+      Pi _ _ a b -> loop a && loop b+      App f a -> loop f && loop a && case App f a of+          App (Lam _ _ _) _ -> False+          App (App (App (App NaturalFold (NaturalLit _)) _) _) _ -> False+          App NaturalBuild _ -> False+          App NaturalIsZero (NaturalLit _) -> False+          App NaturalEven (NaturalLit _) -> False+          App NaturalOdd (NaturalLit _) -> False+          App NaturalShow (NaturalLit _) -> False+          App DateShow (DateLiteral _) -> False+          App TimeShow (TimeLiteral _ _) -> False+          App TimeZoneShow (TimeZoneLiteral _) -> False+          App (App NaturalSubtract (NaturalLit _)) (NaturalLit _) -> False+          App (App NaturalSubtract (NaturalLit 0)) _ -> False+          App (App NaturalSubtract _) (NaturalLit 0) -> False+          App (App NaturalSubtract x) y -> not (Eval.judgmentallyEqual x y)+          App NaturalToInteger (NaturalLit _) -> False+          App IntegerNegate (IntegerLit _) -> False+          App IntegerClamp (IntegerLit _) -> False+          App IntegerShow (IntegerLit _) -> False+          App IntegerToDouble (IntegerLit _) -> False+          App DoubleShow (DoubleLit _) -> False+          App (App ListBuild _) _ -> False+          App (App (App (App (App (App ListFold _) (ListLit _ _)) _) _) _) _ -> False+          App (App ListLength _) (ListLit _ _) -> False+          App (App ListHead _) (ListLit _ _) -> False+          App (App ListLast _) (ListLit _ _) -> False+          App (App ListIndexed _) (ListLit _ _) -> False+          App (App ListReverse _) (ListLit _ _) -> False+          App TextShow (TextLit (Chunks [] _)) ->+              False+          App (App (App TextReplace (TextLit (Chunks [] ""))) _) _ ->+              False+          App (App (App TextReplace (TextLit (Chunks [] _))) _) (TextLit _) ->+              False+          _ -> True+      Let _ _ -> False+      Annot _ _ -> False+      Bool -> True+      BoolLit _ -> True+      BoolAnd x y -> loop x && loop y && decide x y+        where+          decide (BoolLit _)  _          = False+          decide  _          (BoolLit _) = False+          decide  l           r          = not (Eval.judgmentallyEqual l r)+      BoolOr x y -> loop x && loop y && decide x y+        where+          decide (BoolLit _)  _          = False+          decide  _          (BoolLit _) = False+          decide  l           r          = not (Eval.judgmentallyEqual l r)+      BoolEQ x y -> loop x && loop y && decide x y+        where+          decide (BoolLit True)  _             = False+          decide  _             (BoolLit True) = False+          decide  l              r             = not (Eval.judgmentallyEqual l r)+      BoolNE x y -> loop x && loop y && decide x y+        where+          decide (BoolLit False)  _               = False+          decide  _              (BoolLit False ) = False+          decide  l               r               = not (Eval.judgmentallyEqual l r)+      BoolIf x y z ->+          loop x && loop y && loop z && decide x y z+        where+          decide (BoolLit _)  _              _              = False+          decide  _          (BoolLit True) (BoolLit False) = False+          decide  _           l              r              = not (Eval.judgmentallyEqual l r)+      Bytes -> True+      BytesLit _ -> True+      Natural -> True+      NaturalLit _ -> True+      NaturalFold -> True+      NaturalBuild -> True+      NaturalIsZero -> True+      NaturalEven -> True+      NaturalOdd -> True+      NaturalShow -> True+      NaturalSubtract -> True+      NaturalToInteger -> True+      NaturalPlus x y -> loop x && loop y && decide x y+        where+          decide (NaturalLit 0)  _             = False+          decide  _             (NaturalLit 0) = False+          decide (NaturalLit _) (NaturalLit _) = False+          decide  _              _             = True+      NaturalTimes x y -> loop x && loop y && decide x y+        where+          decide (NaturalLit 0)  _             = False+          decide  _             (NaturalLit 0) = False+          decide (NaturalLit 1)  _             = False+          decide  _             (NaturalLit 1) = False+          decide (NaturalLit _) (NaturalLit _) = False+          decide  _              _             = True+      Integer -> True+      IntegerLit _ -> True+      IntegerClamp -> True+      IntegerNegate -> True+      IntegerShow -> True+      IntegerToDouble -> True+      Double -> True+      DoubleLit _ -> True+      DoubleShow -> True+      Text -> True+      TextLit (Chunks [("", _)] "") -> False+      TextLit (Chunks xys _) -> all (all check) xys+        where+          check y = loop y && case y of+              TextLit _ -> False+              _         -> True+      TextAppend _ _ -> False+      TextReplace -> True+      TextShow -> True+      Date -> True+      DateLiteral _ -> True+      DateShow -> True+      Time -> True+      TimeLiteral _ _ -> True+      TimeShow -> True+      TimeZone -> True+      TimeZoneLiteral _ -> True+      TimeZoneShow -> True+      List -> True+      ListLit t es -> all loop t && all loop es+      ListAppend x y -> loop x && loop y && decide x y+        where+          decide (ListLit _ m)  _            | Data.Sequence.null m = False+          decide  _            (ListLit _ n) | Data.Sequence.null n = False+          decide (ListLit _ _) (ListLit _ _)                        = False+          decide  _             _                                   = True+      ListBuild -> True+      ListFold -> True+      ListLength -> True+      ListHead -> True+      ListLast -> True+      ListIndexed -> True+      ListReverse -> True+      Optional -> True+      Some a -> loop a+      None -> True+      Record kts -> Dhall.Map.isSorted kts && all decide kts+        where+          decide (RecordField Nothing exp' Nothing Nothing) = loop exp'+          decide _ = False+      RecordLit kvs -> Dhall.Map.isSorted kvs && all decide kvs+        where+          decide (RecordField Nothing exp' Nothing Nothing) = loop exp'+          decide _ = False+      Union kts -> Dhall.Map.isSorted kts && all (all loop) kts+      Combine _ _ x y -> loop x && loop y && decide x y+        where+          decide (RecordLit m) _ | Data.Foldable.null m = False+          decide _ (RecordLit n) | Data.Foldable.null n = False+          decide (RecordLit _) (RecordLit _) = False+          decide  _ _ = True+      CombineTypes _ x y -> loop x && loop y && decide x y+        where+          decide (Record m) _ | Data.Foldable.null m = False+          decide _ (Record n) | Data.Foldable.null n = False+          decide (Record _) (Record _) = False+          decide  _ _ = True+      Prefer _ _ x y -> loop x && loop y && decide x y+        where+          decide (RecordLit m) _ | Data.Foldable.null m = False+          decide _ (RecordLit n) | Data.Foldable.null n = False+          decide (RecordLit _) (RecordLit _) = False+          decide l r = not (Eval.judgmentallyEqual l r)+      RecordCompletion _ _ -> False+      Merge x y t -> loop x && loop y && all loop t && case x of+          RecordLit _ -> case y of+              Field (Union _) _ -> False+              App (Field (Union _) _) _ -> False+              Some _ -> False+              App None _ -> False+              _ -> True+          _ -> True+      ToMap x t -> case x of+          RecordLit _ -> False+          _ -> loop x && all loop t+      ShowConstructor x -> loop x && case x of+          Field (Union kts) (Syntax.fieldSelectionLabel -> k) ->+              case Dhall.Map.lookup k kts of+                  Just Nothing -> False+                  _            -> True+          App (Field (Union kts) (Syntax.fieldSelectionLabel -> k)) _ ->+              case Dhall.Map.lookup k kts of+                  Just (Just _) -> False+                  _             -> True+          Some _ -> False+          App None _ -> False+          _ -> True+      Field r (FieldSelection Nothing k Nothing) -> case r of+          RecordLit _ -> False+          Project _ _ -> False+          Prefer _ _ (RecordLit m) _ -> Dhall.Map.keys m == [k] && loop r+          Prefer _ _ _ (RecordLit _) -> False+          Combine _ _ (RecordLit m) _ -> Dhall.Map.keys m == [k] && loop r+          Combine _ _ _ (RecordLit m) -> Dhall.Map.keys m == [k] && loop r+          _ -> loop r+      Field _ _ -> False+      Project r p -> loop r &&+          case p of+              Left s -> case r of+                  RecordLit _ -> False+                  Project _ _ -> False+                  Prefer _ _ _ (RecordLit _) -> False+                  _ -> not (null s) && Data.Set.toList (Data.Set.fromList s) == s+              Right e' -> case e' of+                  Record _ -> False+                  _ -> loop e'+      Assert t -> loop t+      Equivalent _ l r -> loop l && loop r+      With{} -> False+      Note _ e' -> loop e'+      ImportAlt _ _ -> False+      Embed _ -> True++{-| Detect if the given variable is free within the given expression++>>> "x" `freeIn` "x"+True+>>> "x" `freeIn` "y"+False+>>> "x" `freeIn` Lam mempty (Syntax.makeFunctionBinding "x" (Const Type)) "x"+False+-}+freeIn :: Eq a => Var -> Expr s a -> Bool+variable@(V var i) `freeIn` expression =+    subst variable (Var (V var (i + 1))) strippedExpression+      /= strippedExpression+  where+    denote' :: Expr t b -> Expr () b+    denote' = Syntax.denote++    strippedExpression = denote' expression+{-# INLINABLE freeIn #-}++{- $setup+>>> import Dhall.Syntax (Const(..))+-}
src/Dhall/Optics.hs view
@@ -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,5 +1,5 @@-{-# LANGUAGE CPP             #-}-{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards   #-}  -- | This module contains Dhall's parsing logic @@ -7,31 +7,35 @@     -- * Utilities       exprFromText     , exprAndHeaderFromText+    , censor+    , createHeader      -- * Parsers     , expr, exprA      -- * Types+    , Header(..)     , Src(..)     , SourcedException(..)     , ParseError(..)     , Parser(..)     ) where -import Control.Exception (Exception)-import Data.Semigroup (Semigroup(..))-import Data.Text (Text)-import Data.Void (Void)-import Dhall.Core-import Dhall.Src (Src(..))-import Prelude hiding (const, pi)+import Control.Applicative (many)+import Control.Exception   (Exception)+import Data.Text           (Text)+import Data.Void           (Void)+import Dhall.Src           (Src (..))+import Dhall.Syntax+import Text.Megaparsec     (ParseErrorBundle (..), PosState (..)) -import qualified Data.Text+import qualified Data.Text       as Text+import qualified Dhall.Core      as Core import qualified Text.Megaparsec  import Dhall.Parser.Combinators-import Dhall.Parser.Token import Dhall.Parser.Expression+import Dhall.Parser.Token       hiding (text)  -- | Parser for a top-level Dhall expression expr :: Parser (Expr Src Import)@@ -41,28 +45,39 @@ -- over any parseable type, allowing the language to be extended as needed. exprA :: Parser a -> Parser (Expr Src a) exprA = completeExpression+{-# DEPRECATED exprA "Support for parsing custom imports will be dropped in a future release" #-}  -- | A parsing error-data ParseError = ParseError-#if MIN_VERSION_megaparsec(7, 0, 0)-    { unwrap :: Text.Megaparsec.ParseErrorBundle Text Void-#else-    { unwrap :: Text.Megaparsec.ParseError Char Void-#endif+data ParseError = ParseError {+      unwrap :: Text.Megaparsec.ParseErrorBundle Text Void     , input  :: Text     } +{-| Replace the source code with spaces when rendering error messages++    This utility is used to implement the @--censor@ flag+-}+censor :: ParseError -> ParseError+censor parseError =+    parseError+        { unwrap =+            (unwrap parseError)+                { bundlePosState =+                    (bundlePosState (unwrap parseError))+                        { pstateInput =+                            Core.censorText+                                (pstateInput (bundlePosState (unwrap parseError)))+                        }+                }+        }+ instance Show ParseError where     show (ParseError {..}) =-#if MIN_VERSION_megaparsec(7, 0, 0)       "\n\ESC[1;31mError\ESC[0m: Invalid input\n\n" <> Text.Megaparsec.errorBundlePretty unwrap-#else-      "\n\ESC[1;31mError\ESC[0m: Invalid input\n\n" <> Text.Megaparsec.parseErrorPretty unwrap-#endif  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@@ -70,29 +85,46 @@   -> Either ParseError (Expr Src Import) exprFromText delta text = fmap snd (exprAndHeaderFromText delta text) -{-| Like `exprFromText` but also returns the leading comments and whitespace-    (i.e. header) up to the last newline before the code begins+-- | A header corresponds to the leading comment at the top of a Dhall file.+--+-- The header includes comment characters but is stripped of leading spaces and+-- trailing newlines+newtype Header = Header Text deriving Show -    In other words, if you have a Dhall file of the form:+-- | Create a header with stripped leading spaces and trailing newlines+createHeader :: Text -> Header+createHeader text = Header (prefix <> newSuffix)+  where+    isWhitespace c = c == ' ' || c == '\n' || c == '\r' || c == '\t' -> -- Comment 1-> {- Comment -} 2+    prefix = Text.dropAround isWhitespace text -    Then this will preserve @Comment 1@, but not @Comment 2@+    newSuffix+        | Text.null prefix = ""+        | otherwise        = "\n" -    This is used by @dhall-format@ to preserve leading comments and whitespace--}+-- | Like `exprFromText` but also returns the leading comments and whitespace+-- (i.e. header) up to the last newline before the code begins+--+-- In other words, if you have a Dhall file of the form:+--+-- > -- Comment 1+-- > {- Comment -} 2+--+-- Then this will preserve @Comment 1@, but not @Comment 2@+--+-- This is used by @dhall-format@ to preserve leading comments and whitespace exprAndHeaderFromText     :: String -- ^ User-friendly name describing the input expression,               --   used in parsing error messages     -> Text   -- ^ Input expression to parse-    -> Either ParseError (Text, Expr Src Import)+    -> Either ParseError (Header, Expr Src Import) exprAndHeaderFromText delta text = case result of     Left errInfo   -> Left (ParseError { unwrap = errInfo, input = text })-    Right (txt, r) -> Right (Data.Text.dropWhileEnd (/= '\n') txt, r)+    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,45 +1,53 @@ {-# 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.Sequence              (ViewL (..))-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.Sequence-import qualified Data.Set+import qualified Data.Char                   as Char import qualified Data.Text-import qualified Data.Text.Prettyprint.Doc               as Pretty-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-#if !MIN_VERSION_megaparsec(7, 0, 0)-import qualified Text.Megaparsec.Char as Text.Megaparsec (satisfy)-#endif import qualified Text.Megaparsec.Char import qualified Text.Parser.Char import qualified Text.Parser.Combinators import qualified Text.Parser.Token.Style +-- | An exception annotated with a `Src` span data SourcedException e = SourcedException Src e  instance Exception e => Exception (SourcedException e)@@ -50,11 +58,11 @@         <>  "\n"         <>  "\n"         <>  Pretty.renderString-                (Pretty.layoutPretty Dhall.Pretty.layoutOpts (pretty source))+                (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@@ -128,9 +136,7 @@     -- {-# INLINE mplus #-}  instance Text.Megaparsec.MonadParsec Void Text Parser where-    failure u e    = Parser (Text.Megaparsec.failure u e)--    fancyFailure e = Parser (Text.Megaparsec.fancyFailure e)+    parseError e = Parser (Text.Megaparsec.parseError e)      label l (Parser p) = Parser (Text.Megaparsec.label l p) @@ -163,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) @@ -198,11 +204,7 @@    notChar = Text.Megaparsec.Char.char -#if MIN_VERSION_megaparsec(7, 0, 0)   anyChar = Text.Megaparsec.anySingle-#else-  anyChar = Text.Megaparsec.Char.anyChar-#endif    string = fmap Data.Text.unpack . Text.Megaparsec.Char.string . fromString @@ -211,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@@ -228,47 +232,61 @@     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+-- | 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-    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+    m = Dhall.Map.fromListWithKey err (map (\(k, v) -> (k, pure v)) kvs) -toMap :: [(Text, a)] -> Parser (Map Text a)-toMap kvs = do-    let adapt (k, v) = (k, pure v)-    let m = fromListWith (<|>) (fmap adapt kvs)-    let action k vs = case Data.Sequence.viewl vs of-            EmptyL  -> empty-            v :< vs' ->-                if null vs'-                then pure v-                else-                    Text.Parser.Combinators.unexpected+    err k _v1 _v2 = Text.Parser.Combinators.unexpected                         ("duplicate field: " ++ Data.Text.unpack k)-    Dhall.Map.traverseWithKey action m++-- | Creates a 'Map Text a' using the provided combining function and the+--   key-value pairs+toMapWith+    :: (Text -> Parser a -> Parser a -> Parser a)+    -> [(Text, a)]+    -> Parser (Map Text a)+toMapWith combine kvs = sequence m   where-    fromListWith combine = foldr cons mempty-      where-        cons (k, v) = Dhall.Map.insertWith combine k v+    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,840 +1,1279 @@ {-# LANGUAGE CPP                 #-} {-# LANGUAGE NamedFieldPuns      #-}-{-# LANGUAGE RecordWildCards     #-}-{-# LANGUAGE OverloadedLists     #-}-{-# LANGUAGE OverloadedStrings   #-}-{-# LANGUAGE ScopedTypeVariables #-}---- | Parsing Dhall expressions.-module Dhall.Parser.Expression where--import Control.Applicative (Alternative(..), optional)-import Data.ByteArray.Encoding (Base(..))-import Data.Functor (void)-import Data.List.NonEmpty (NonEmpty(..))-import Data.Semigroup (Semigroup(..))-import Data.Text (Text)-import Dhall.Core-import Dhall.Src (Src(..))-import Prelude hiding (const, pi)-import Text.Parser.Combinators (choice, try, (<?>))--import qualified Crypto.Hash-import qualified Data.ByteArray.Encoding-import qualified Data.ByteString-import qualified Data.Char-import qualified Data.Foldable-import qualified Data.List.NonEmpty-import qualified Data.Sequence-import qualified Data.Text-import qualified Data.Text.Encoding-import qualified Text.Megaparsec-#if !MIN_VERSION_megaparsec(7, 0, 0)-import qualified Text.Megaparsec.Char as Text.Megaparsec-#endif-import qualified Text.Parser.Char--import Dhall.Parser.Combinators-import Dhall.Parser.Token--getSourcePos :: Text.Megaparsec.MonadParsec e s m =>-                m Text.Megaparsec.SourcePos-getSourcePos =-#if MIN_VERSION_megaparsec(7, 0, 0)-    Text.Megaparsec.getSourcePos-#else-    Text.Megaparsec.getPosition-#endif-{-# INLINE getSourcePos #-}--getOffset :: Text.Megaparsec.MonadParsec e s m => m Int-#if MIN_VERSION_megaparsec(7, 0, 0)-getOffset = Text.Megaparsec.stateOffset <$> Text.Megaparsec.getParserState-#else-getOffset = Text.Megaparsec.stateTokensProcessed <$> Text.Megaparsec.getParserState-#endif-{-# INLINE getOffset #-}--setOffset :: Text.Megaparsec.MonadParsec e s m => Int -> m ()-#if MIN_VERSION_megaparsec(7, 0, 0)-setOffset o = Text.Megaparsec.updateParserState $ \(Text.Megaparsec.State s _ pst) ->-  Text.Megaparsec.State s o pst-#else-setOffset o = Text.Megaparsec.updateParserState $ \(Text.Megaparsec.State s p _ stw) ->-  Text.Megaparsec.State s p o stw-#endif-{-# INLINE setOffset #-}--noted :: Parser (Expr Src a) -> Parser (Expr Src a)-noted parser = do-    before      <- getSourcePos-    (tokens, e) <- Text.Megaparsec.match parser-    after       <- getSourcePos-    let src₀ = Src before after tokens-    case e of-        Note src₁ _ | laxSrcEq src₀ src₁ -> return e-        _                                -> return (Note src₀ e)--shallowDenote :: Expr s a -> Expr s a-shallowDenote (Note _ e) = shallowDenote e-shallowDenote         e  = e--completeExpression :: Parser a -> Parser (Expr Src a)-completeExpression embedded = completeExpression_-  where-    completeExpression_ = do-        whitespace-        expression--    expression =-        noted-            ( choice-                [ alternative0-                , alternative1-                , alternative2-                , alternative3-                , alternative4-                ]-            ) <?> "expression"-      where-        alternative0 = do-            _lambda-            _openParens-            a <- label-            _colon-            b <- expression-            _closeParens-            _arrow-            c <- expression-            return (Lam a b c)--        alternative1 = do-            _if-            a <- expression-            _then-            b <- expression-            _else-            c <- expression-            return (BoolIf a b c)--        alternative2 = do-            let binding = do-                    _let--                    c <- label-                    d <- optional (do-                        _colon-                        expression )--                    _equal--                    e <- expression--                    return (Binding c d e)--            as <- Data.List.NonEmpty.some1 binding--            _in--            b <- expression--            return (Let as b)--        alternative3 = do-            _forall-            _openParens-            a <- label-            _colon-            b <- expression-            _closeParens-            _arrow-            c <- expression-            return (Pi a b c)--        alternative4 = do-            a <- operatorExpression--            let alternative4A = do-                    _arrow-                    b <- expression-                    return (Pi "_" a b)--            let alternative4B = do-                    _colon--                    b <- expression--                    case (shallowDenote a, shallowDenote b) of-                        (ListLit _ xs, App f c) ->-                            case shallowDenote f of-                                List     -> case xs of-                                    [] -> return (ListLit (Just c) xs)-                                    _  -> return (Annot a b)-                                Optional -> case xs of-                                    [x] -> return (OptionalLit c (Just x))-                                    []  -> return (OptionalLit c Nothing)-                                    _   -> return (Annot a b)-                                _ ->-                                    return (Annot a b)-                        (Merge c d _, e) ->-                            return (Merge c d (Just e))-                        _ -> return (Annot a b)--            alternative4A <|> alternative4B <|> pure a--    operatorExpression = precedence0Expression--    makeOperatorExpression subExpression operatorParser =-            noted (do-                a <- subExpression-                b <- Text.Megaparsec.many $ do-                    op <- operatorParser-                    r  <- subExpression--                    return (\l -> l `op` r)-                return (foldl (\x f -> f x) a b) )--    precedence0Operator =-                ImportAlt   <$ _importAlt-            <|> BoolOr      <$ _or-            <|> TextAppend  <$ _textAppend-            <|> NaturalPlus <$ _plus-            <|> ListAppend  <$ _listAppend--    precedence1Operator =-                BoolAnd     <$ _and-            <|> Combine     <$ _combine--    precedence2Operator =-                CombineTypes <$ _combineTypes-            <|> Prefer       <$ _prefer-            <|> NaturalTimes <$ _times-            <|> BoolEQ       <$ _doubleEqual--    precedence3Operator = BoolNE <$ _notEqual--    precedence0Expression =-            makeOperatorExpression precedence1Expression precedence0Operator--    precedence1Expression =-            makeOperatorExpression precedence2Expression precedence1Operator--    precedence2Expression =-            makeOperatorExpression precedence3Expression precedence2Operator--    precedence3Expression =-            makeOperatorExpression applicationExpression precedence3Operator--    applicationExpression = do-            f <-    (do _Some; return Some)-                <|> return id-            a <- noted importExpression-            b <- Text.Megaparsec.many (noted importExpression)-            return (foldl app (f a) b)-          where-            app nL@(Note (Src before _ bytesL) _) nR@(Note (Src _ after bytesR) _) =-                Note (Src before after (bytesL <> bytesR)) (App nL nR)-            app nL nR =-                App nL nR--    importExpression = noted (choice [ alternative0, alternative1 ])-          where-            alternative0 = do-                a <- embedded-                return (Embed a)--            alternative1 = selectorExpression--    selectorExpression = noted (do-            a <- primitiveExpression--            let recordType = _openParens *> expression <* _closeParens--            let field               x  e = Field   e  x-            let projectBySet        xs e = Project e (Left  xs)-            let projectByExpression xs e = Project e (Right xs)--            let alternatives =-                        fmap field               anyLabel-                    <|> fmap projectBySet        labels-                    <|> fmap projectByExpression recordType--            b <- Text.Megaparsec.many (try (do _dot; alternatives))-            return (foldl (\e k -> k e) a b) )--    primitiveExpression =-            noted-                ( choice-                    [ alternative00-                    , alternative01-                    , alternative02-                    , alternative03-                    , alternative04-                    , alternative05-                    , alternative06-                    , alternative07-                    , alternative37-                    , alternative09--                    , builtin <?> "built-in expression"-                    ]-                )-            <|> alternative38-          where-            alternative00 = do-                n <- getOffset-                a <- try doubleLiteral-                b <- if isInfinite a-                       then setOffset n *> fail "double out of bounds"-                       else return a-                return (DoubleLit b)--            alternative01 = do-                a <- try naturalLiteral-                return (NaturalLit a)--            alternative02 = do-                a <- try integerLiteral-                return (IntegerLit a)--            alternative03 = textLiteral--            alternative04 = (do-                _openBrace-                a <- recordTypeOrLiteral-                _closeBrace-                return a ) <?> "record type or literal"--            alternative05 = (do-                _openAngle-                a <- unionTypeOrLiteral-                _closeAngle-                return a ) <?> "union type or literal"--            alternative06 = listLiteral--            alternative07 = do-                _merge-                a <- importExpression-                b <- importExpression-                return (Merge a b Nothing)--            alternative09 = do-                a <- try doubleInfinity-                return (DoubleLit a)--            builtin = do-                let predicate c =-                            c == 'N'-                        ||  c == 'I'-                        ||  c == 'D'-                        ||  c == 'L'-                        ||  c == 'O'-                        ||  c == 'B'-                        ||  c == 'S'-                        ||  c == 'T'-                        ||  c == 'F'-                        ||  c == 'K'--                let nan = (0.0/0.0)--                c <- Text.Megaparsec.lookAhead (Text.Megaparsec.satisfy predicate)--                case c of-                    'N' ->-                        choice-                            [ NaturalFold      <$ _NaturalFold-                            , NaturalBuild     <$ _NaturalBuild-                            , NaturalIsZero    <$ _NaturalIsZero-                            , NaturalEven      <$ _NaturalEven-                            , NaturalOdd       <$ _NaturalOdd-                            , NaturalToInteger <$ _NaturalToInteger-                            , NaturalToInteger <$ _NaturalToInteger-                            , NaturalShow      <$ _NaturalShow-                            , Natural          <$ _Natural-                            , None             <$ _None-                            , DoubleLit nan    <$ _NaN-                            ]-                    'I' ->-                        choice-                            [ IntegerShow      <$ _IntegerShow-                            , IntegerToDouble  <$ _IntegerToDouble-                            , Integer          <$ _Integer-                            ]--                    'D' ->-                        choice-                            [ DoubleShow       <$ _DoubleShow-                            , Double           <$ _Double-                            ]-                    'L' ->-                        choice-                            [ ListBuild        <$ _ListBuild-                            , ListFold         <$ _ListFold-                            , ListLength       <$ _ListLength-                            , ListHead         <$ _ListHead-                            , ListLast         <$ _ListLast-                            , ListIndexed      <$ _ListIndexed-                            , ListReverse      <$ _ListReverse-                            , List             <$ _List-                            ]-                    'O' ->-                        choice-                            [ OptionalFold     <$ _OptionalFold-                            , OptionalBuild    <$ _OptionalBuild-                            , Optional         <$ _Optional-                            ]-                    'B' ->    Bool             <$ _Bool-                    'S' ->    Const Sort       <$ _Sort-                    'T' ->-                        choice-                            [ TextShow         <$ _TextShow-                            , Text             <$ _Text-                            , BoolLit True     <$ _True-                            , Const Type       <$ _Type-                            ]-                    'F' ->    BoolLit False    <$ _False-                    'K' ->    Const Kind       <$ _Kind-                    _   ->    empty--            alternative37 = do-                a <- identifier-                return (Var a)--            alternative38 = do-                _openParens-                a <- expression-                _closeParens-                return a--    doubleQuotedChunk =-            choice-                [ interpolation-                , unescapedCharacterFast-                , unescapedCharacterSlow-                , escapedCharacter-                ]-          where-            interpolation = do-                _ <- Text.Parser.Char.text "${"-                e <- completeExpression_-                _ <- Text.Parser.Char.char '}'-                return (Chunks [(mempty, e)] mempty)--            unescapedCharacterFast = do-                t <- Text.Megaparsec.takeWhile1P Nothing predicate-                return (Chunks [] t)-              where-                predicate c =-                    (   ('\x20' <= c && c <= '\x21'    )-                    ||  ('\x23' <= c && c <= '\x5B'    )-                    ||  ('\x5D' <= c && c <= '\x10FFFF')-                    ) && c /= '$'--            unescapedCharacterSlow = do-                _ <- Text.Parser.Char.char '$'-                return (Chunks [] "$")--            escapedCharacter = do-                _ <- Text.Parser.Char.char '\\'-                c <- choice-                    [ quotationMark-                    , dollarSign-                    , backSlash-                    , forwardSlash-                    , backSpace-                    , formFeed-                    , lineFeed-                    , carriageReturn-                    , tab-                    , unicode-                    ]-                return (Chunks [] (Data.Text.singleton c))-              where-                quotationMark = Text.Parser.Char.char '"'--                dollarSign = Text.Parser.Char.char '$'--                backSlash = Text.Parser.Char.char '\\'--                forwardSlash = Text.Parser.Char.char '/'--                backSpace = do _ <- Text.Parser.Char.char 'b'; return '\b'--                formFeed = do _ <- Text.Parser.Char.char 'f'; return '\f'--                lineFeed = do _ <- Text.Parser.Char.char 'n'; return '\n'--                carriageReturn = do _ <- Text.Parser.Char.char 'r'; return '\r'--                tab = do _ <- Text.Parser.Char.char 't'; return '\t'--                unicode = do-                    _  <- Text.Parser.Char.char 'u';-                    n0 <- hexNumber-                    n1 <- hexNumber-                    n2 <- hexNumber-                    n3 <- hexNumber-                    let n = ((n0 * 16 + n1) * 16 + n2) * 16 + n3-                    return (Data.Char.chr n)--    doubleQuotedLiteral = do-            _      <- Text.Parser.Char.char '"'-            chunks <- Text.Megaparsec.many doubleQuotedChunk-            _      <- Text.Parser.Char.char '"'-            return (mconcat chunks)--    singleQuoteContinue =-            choice-                [ escapeSingleQuotes-                , interpolation-                , escapeInterpolation-                , endLiteral-                , unescapedCharacterFast-                , unescapedCharacterSlow-                , tab-                , endOfLine-                ]-          where-                escapeSingleQuotes = do-                    _ <- "'''" :: Parser Text-                    b <- singleQuoteContinue-                    return ("''" <> b)--                interpolation = do-                    _ <- Text.Parser.Char.text "${"-                    a <- completeExpression_-                    _ <- Text.Parser.Char.char '}'-                    b <- singleQuoteContinue-                    return (Chunks [(mempty, a)] mempty <> b)--                escapeInterpolation = do-                    _ <- Text.Parser.Char.text "''${"-                    b <- singleQuoteContinue-                    return ("${" <> b)--                endLiteral = do-                    _ <- Text.Parser.Char.text "''"-                    return mempty--                unescapedCharacterFast = do-                    a <- Text.Megaparsec.takeWhile1P Nothing predicate-                    b <- singleQuoteContinue-                    return (Chunks [] a <> b)-                  where-                    predicate c =-                        ('\x20' <= c && c <= '\x10FFFF') && c /= '$' && c /= '\''--                unescapedCharacterSlow = do-                    a <- satisfy predicate-                    b <- singleQuoteContinue-                    return (Chunks [] a <> b)-                  where-                    predicate c = c == '$' || c == '\''--                endOfLine = do-                    a <- "\n" <|> "\r\n"-                    b <- singleQuoteContinue-                    return (Chunks [] a <> b)--                tab = do-                    _ <- Text.Parser.Char.char '\t'-                    b <- singleQuoteContinue-                    return ("\t" <> b)--    singleQuoteLiteral = do-            _ <- Text.Parser.Char.text "''"-            _ <- endOfLine-            a <- singleQuoteContinue--            return (toDoubleQuoted a)-          where-            endOfLine =-                    void (Text.Parser.Char.char '\n'  )-                <|> void (Text.Parser.Char.text "\r\n")--    textLiteral = (do-            literal <- doubleQuotedLiteral <|> singleQuoteLiteral-            whitespace-            return (TextLit literal) ) <?> "text literal"--    recordTypeOrLiteral =-            choice-                [ alternative0-                , alternative1-                , alternative2-                ]-          where-            alternative0 = do-                _equal-                return (RecordLit mempty)--            alternative1 = nonEmptyRecordTypeOrLiteral--            alternative2 = return (Record mempty)--    nonEmptyRecordTypeOrLiteral = do-            a <- anyLabel--            let nonEmptyRecordType = do-                    _colon-                    b <- expression-                    e <- Text.Megaparsec.many (do-                        _comma-                        c <- anyLabel-                        _colon-                        d <- expression-                        return (c, d) )-                    m <- toMap ((a, b) : e)-                    return (Record m)--            let nonEmptyRecordLiteral = do-                    _equal-                    b <- expression-                    e <- Text.Megaparsec.many (do-                        _comma-                        c <- anyLabel-                        _equal-                        d <- expression-                        return (c, d) )-                    m <- toMap ((a, b) : e)-                    return (RecordLit m)--            nonEmptyRecordType <|> nonEmptyRecordLiteral--    unionTypeOrLiteral =-                nonEmptyUnionTypeOrLiteral-            <|> return (Union mempty)--    nonEmptyUnionTypeOrLiteral = do-            (f, kvs) <- loop-            m <- toMap kvs-            return (f m)-          where-            loop = do-                a <- anyLabel--                let alternative0 = do-                        _equal-                        b <- expression-                        kvs <- Text.Megaparsec.many (do-                            _bar-                            c <- anyLabel-                            d <- optional (do _colon; expression)-                            return (c, d) )-                        return (UnionLit a b, kvs)--                let alternative1 = do-                        b <- optional (do _colon; expression)--                        let alternative2 = do-                                _bar-                                (f, kvs) <- loop-                                return (f, (a, b):kvs)--                        let alternative3 = return (Union, [(a, b)])--                        alternative2 <|> alternative3--                alternative0 <|> alternative1--    listLiteral = (do-            _openBracket-            a <- Text.Megaparsec.sepBy expression _comma-            _closeBracket-            return (ListLit Nothing (Data.Sequence.fromList a)) ) <?> "list literal"--env :: Parser ImportType-env = do-    _ <- Text.Parser.Char.text "env:"-    a <- (alternative0 <|> alternative1)-    whitespace-    return (Env a)-  where-    alternative0 = bashEnvironmentVariable--    alternative1 = do-        _ <- Text.Parser.Char.char '"'-        a <- posixEnvironmentVariable-        _ <- Text.Parser.Char.char '"'-        return a--localRaw :: Parser ImportType-localRaw =-    choice-        [ parentPath-        , herePath-        , homePath-        , try absolutePath-        ]-  where-    parentPath = do-        _    <- ".." :: Parser Text-        file <- file_ FileComponent--        return (Local Parent file)--    herePath = do-        _    <- "." :: Parser Text-        file <- file_ FileComponent--        return (Local Here file)--    homePath = do-        _    <- "~" :: Parser Text-        file <- file_ FileComponent--        return (Local Home file)--    absolutePath = do-        file <- file_ FileComponent--        return (Local Absolute file)--local :: Parser ImportType-local = do-    a <- localRaw-    whitespace-    return a--http :: Parser ImportType-http = do-    url <- httpRaw-    whitespace-    headers <- optional (do-        _using-        (completeExpression import_ <|> (_openParens *> completeExpression import_ <* _closeParens)) )-    return (Remote (url { headers }))--missing :: Parser ImportType-missing = do-  _missing-  return Missing--importType_ :: Parser ImportType-importType_ = do-    let predicate c =-            c == '~' || c == '.' || c == '/' || c == 'h' || c == 'e' || c == 'm'--    _ <- Text.Megaparsec.lookAhead (Text.Megaparsec.satisfy predicate)--    choice [ local, http, env, missing ]--importHashed_ :: Parser ImportHashed-importHashed_ = do-    importType <- importType_-    hash       <- optional importHash_-    return (ImportHashed {..})-  where-    importHash_ = do-        _ <- Text.Parser.Char.text "sha256:"-        text <- count 64 (satisfy hexdig <?> "hex digit")-        whitespace-        let strictBytes16 = Data.Text.Encoding.encodeUtf8 text-        strictBytes <- case Data.ByteArray.Encoding.convertFromBase Base16 strictBytes16 of-            Left  string      -> fail string-            Right strictBytes -> return (strictBytes :: Data.ByteString.ByteString)-        case Crypto.Hash.digestFromByteString strictBytes of-          Nothing -> fail "Invalid sha256 hash"-          Just h  -> pure h--import_ :: Parser Import-import_ = (do-    importHashed <- importHashed_-    importMode   <- alternative <|> pure Code-    return (Import {..}) ) <?> "import"-  where-    alternative = do-        _as-        _Text-        return RawText---- | Similar to `Dhall.Core.renderChunks` except that this doesn't bother to--- render interpolated expressions to avoid a `Buildable a` constraint.  The--- interpolated contents are not necessary for computing how much to dedent a--- multi-line string------ This also doesn't include the surrounding quotes since they would interfere--- with the whitespace detection-renderChunks :: Chunks s a -> Text-renderChunks (Chunks a b) = foldMap renderChunk a <> b-  where-    renderChunk :: (Text, Expr s a) -> Text-    renderChunk (c, _) = c <> "${x}"--splitOn :: Text -> Text -> NonEmpty Text-splitOn needle haystack =-    case Data.Text.splitOn needle haystack of-        []     -> "" :| []-        t : ts -> t  :| ts--linesLiteral :: Chunks s a -> NonEmpty (Chunks s a)-linesLiteral (Chunks [] suffix) =-    fmap (Chunks []) (splitOn "\n" suffix)-linesLiteral (Chunks ((prefix, interpolation) : pairs₀) suffix₀) =-    foldr-        Data.List.NonEmpty.cons-        (Chunks ((lastLine, interpolation) : pairs₁) suffix₁ :| chunks)-        (fmap (Chunks []) initLines)-  where-    splitLines = splitOn "\n" prefix--    initLines = Data.List.NonEmpty.init splitLines-    lastLine  = Data.List.NonEmpty.last splitLines--    Chunks pairs₁ suffix₁ :| chunks = linesLiteral (Chunks pairs₀ suffix₀)--unlinesLiteral :: NonEmpty (Chunks s a) -> Chunks s a-unlinesLiteral chunks =-    Data.Foldable.fold (Data.List.NonEmpty.intersperse "\n" chunks)--emptyLine :: Chunks s a -> Bool-emptyLine (Chunks [] ""  ) = True-emptyLine (Chunks [] "\r") = True  -- So that `\r\n` is treated as a blank line-emptyLine  _               = False--leadingSpaces :: Chunks s a -> Text-leadingSpaces chunks = Data.Text.takeWhile isSpace firstText-  where-    isSpace c = c == '\x20' || c == '\x09'--    firstText =-        case chunks of-            Chunks                []  suffix -> suffix-            Chunks ((prefix, _) : _ ) _      -> prefix--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--toDoubleQuoted :: Chunks Src a -> Chunks Src a-toDoubleQuoted literal =-    unlinesLiteral (fmap (dropLiteral indent) literals)-  where-    literals = linesLiteral literal--    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 = Data.List.NonEmpty.init literals--        oldLast = Data.List.NonEmpty.last literals--        newInit = filter (not . emptyLine) oldInit--    longestSharedPrefix =-        case filteredLines of-            l : ls ->-                Data.Foldable.foldl' sharedPrefix (leadingSpaces l) (fmap leadingSpaces ls)-            [] ->-                ""--    indent = Data.Text.length longestSharedPrefix+{-# LANGUAGE OverloadedLists     #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE RecordWildCards     #-}+{-# LANGUAGE ScopedTypeVariables #-}++-- | Parsing Dhall expressions.+module Dhall.Parser.Expression where++import Control.Applicative     (Alternative (..), liftA2, optional)+import Data.Foldable           (foldl')+import Data.List.NonEmpty      (NonEmpty (..))+import Data.Text               (Text)+import Dhall.Src               (Src (..))+import Dhall.Syntax+import Text.Parser.Combinators (choice, try, (<?>))++import qualified Control.Monad+import qualified Control.Monad.Combinators          as Combinators+import qualified Control.Monad.Combinators.NonEmpty as Combinators.NonEmpty+import qualified Data.ByteString                    as ByteString+import qualified Data.ByteString.Base16             as Base16+import qualified Data.Char                          as Char+import qualified Data.List+import qualified Data.List.NonEmpty                 as NonEmpty+import qualified Data.Sequence+import qualified Data.Text+import qualified Data.Text.Encoding+import qualified Data.Time                          as Time+import qualified Dhall.Crypto+import qualified Text.Megaparsec++import Dhall.Parser.Combinators+import Dhall.Parser.Token++-- | Get the current source offset (in tokens)+getOffset :: Text.Megaparsec.MonadParsec e s m => m Int+getOffset = Text.Megaparsec.stateOffset <$> Text.Megaparsec.getParserState+{-# INLINE getOffset #-}++-- | Set the current source offset+setOffset :: Text.Megaparsec.MonadParsec e s m => Int -> m ()+setOffset o = Text.Megaparsec.updateParserState $ \state ->+    state+        { Text.Megaparsec.stateOffset = o }+{-# INLINE setOffset #-}++{-| Wrap a `Parser` to still match the same text but return only the `Src`+    span+-}+src :: Parser a -> Parser Src+src parser = do+    before      <- Text.Megaparsec.getSourcePos+    (tokens, _) <- Text.Megaparsec.match parser+    after       <- Text.Megaparsec.getSourcePos+    return (Src before after tokens)++-- | Same as `src`, except also return the parsed value+srcAnd :: Parser a -> Parser (Src, a)+srcAnd parser = do+    before      <- Text.Megaparsec.getSourcePos+    (tokens, x) <- Text.Megaparsec.match parser+    after       <- Text.Megaparsec.getSourcePos+    return (Src before after tokens, x)++{-| Wrap a `Parser` to still match the same text, but to wrap the resulting+    `Expr` in a `Note` constructor containing the `Src` span+-}+noted :: Parser (Expr Src a) -> Parser (Expr Src a)+noted parser = do+    before      <- Text.Megaparsec.getSourcePos+    (tokens, e) <- Text.Megaparsec.match parser+    after       <- Text.Megaparsec.getSourcePos+    let src₀ = Src before after tokens+    case e of+        Note src₁ _ | laxSrcEq src₀ src₁ -> return e+        _                                -> return (Note src₀ e)++{-| Parse a complete expression (with leading and trailing whitespace)++    This corresponds to the @complete-expression@ rule from the official+    grammar+-}+completeExpression :: Parser a -> Parser (Expr Src a)+completeExpression embedded = completeExpression_+  where+    Parsers {..} = parsers embedded++{-| Parse an \"import expression\"++    This is not the same thing as @`fmap` `Embed`@.  This parses any+    expression of the same or higher precedence as an import expression (such+    as a selector expression).  For example, this parses @(1)@++    This corresponds to the @import-expression@ rule from the official grammar+-}+importExpression :: Parser a -> Parser (Expr Src a)+importExpression embedded = importExpression_+  where+    Parsers {..} = parsers embedded++{-| For efficiency (and simplicity) we only expose two parsers from the+    result of the `parsers` function, since these are the only parsers needed+    outside of this module+-}+data Parsers a = Parsers+    { completeExpression_ :: Parser (Expr Src a)+    , importExpression_   :: Parser (Expr Src a)+    , letBinding          :: Parser (Binding Src a)+    }++{-| Parse a numeric `TimeZone`++    This corresponds to the @time-numoffset@ rule from the official grammar+-}+timeNumOffset :: Parser (Expr s a)+timeNumOffset = do+    s <- signPrefix++    hour <- timeHour++    _ <- text ":"++    minute <- timeMinute++    let minutes = s (hour * 60 + minute)++    return (TimeZoneLiteral (Time.TimeZone minutes Prelude.False ""))++{-| Parse a numeric `TimeZone` or a @Z@++    This corresponds to the @time-offset@ rule from the official grammar+-}+timeOffset :: Parser (Expr s a)+timeOffset =+        (do _ <- text "Z"++            return (TimeZoneLiteral (Time.TimeZone 0 Prelude.False ""))+        )+    <|> timeNumOffset++{-| Parse a `Time`++    This corresponds to the @partial-time@ rule from the official grammar+-}+partialTime :: Parser (Expr s a)+partialTime = do+    hour <- timeHour++    _ <- text ":"++    minute <- timeMinute++    _ <- text ":"++    second <- timeSecond++    (fraction, precision) <- timeSecFrac <|> pure (0, 0)++    let time = Time.TimeOfDay hour minute (second + fraction)++    return (TimeLiteral time precision)++{-| Parse a `Date`++    This corresponds to the @full-date@ rule from the official grammar+-}+fullDate :: Parser (Expr s a)+fullDate = do+    year <- dateFullYear++    _ <- text "-"++    month <- dateMonth++    _ <- text "-"++    day <- dateMday++    case Time.fromGregorianValid year month day of+        Nothing -> fail "Invalid calendar day"+        Just d  -> return (DateLiteral d)++{-| Parse a `Date`, `Time`, `TimeZone` or any valid permutation of them as a+    record++    This corresponds to the @temporal-literal@ rule from the official grammar+-}+temporalLiteral :: Parser (Expr s a)+temporalLiteral =+        try (do+            date <- fullDate++            _ <- text "T" <|> text "t"++            time <- partialTime++            timeZone <- timeOffset++            return+                (RecordLit+                    [   ("date"    , makeRecordField date)+                    ,   ("time"    , makeRecordField time)+                    ,   ("timeZone", makeRecordField timeZone)+                    ]+                )+        )+    <|> try (do+            date <- fullDate++            _ <- text "T" <|> text "t"++            time <- partialTime++            return+                (RecordLit+                    [   ("date", makeRecordField date)+                    ,   ("time", makeRecordField time)+                    ]+                )+        )+    <|> try (do+            time <- partialTime++            timeZone <- timeOffset++            return+                (RecordLit+                    [   ("time"    , makeRecordField time)+                    ,   ("timeZone", makeRecordField timeZone)+                    ]+                )+        )+    <|> try fullDate+    <|> try partialTime+    <|> try timeNumOffset++-- | Parse a \"shebang\" line (i.e. an initial line beginning with @#!@)+shebang :: Parser ()+shebang = do+    _ <- text "#!"++    let predicate c = ('\x20' <= c && c <= '\x10FFFF') || c == '\t'++    _ <- Dhall.Parser.Combinators.takeWhile predicate++    _ <- endOfLine++    return ()++-- | Given a parser for imports,+parsers :: forall a. Parser a -> Parsers a+parsers embedded = Parsers{..}+  where+    completeExpression_ =+            whitespace+        *>  expression+        <*  whitespace+        <*  optional lineCommentPrefix++    letBinding = do+        src0 <- try (_let *> src nonemptyWhitespace)++        c <- label++        src1 <- src whitespace++        d <- optional (do+            _colon++            src2 <- src nonemptyWhitespace++            e <- expression++            whitespace++            return (Just src2, e) )++        _equal++        src3 <- src whitespace++        f <- expression++        whitespace++        return (Binding (Just src0) c (Just src1) d (Just src3) f)++    expression =+        noted+            ( choice+                [ alternative0+                , alternative1+                , alternative2+                , alternative3+                , alternative4+                , alternative5+                ]+            ) <?> "expression"+      where+        alternative0 = do+            cs <- _lambda+            whitespace+            _openParens+            src0 <- src whitespace+            a <- label+            src1 <- src whitespace+            _colon+            src2 <- src nonemptyWhitespace+            b <- expression+            whitespace+            _closeParens+            whitespace+            cs' <- _arrow+            whitespace+            c <- expression+            return (Lam (Just (cs <> cs')) (FunctionBinding (Just src0) a (Just src1) (Just src2) b) c)++        alternative1 = do+            try (_if *> nonemptyWhitespace)+            a <- expression+            whitespace+            try (_then *> nonemptyWhitespace)+            b <- expression+            whitespace+            try (_else *> nonemptyWhitespace)+            c <- expression+            return (BoolIf a b c)++        alternative2 = do+            as <- NonEmpty.some1 letBinding++            try (_in *> nonemptyWhitespace)++            b <- expression++            -- 'Note's in let-in-let:+            --+            -- Subsequent @let@s that are not separated by an @in@ only get a+            -- single surrounding 'Note'. For example:+            --+            -- let x = a+            -- let y = b+            -- in  let z = c+            --     in x+            --+            -- is parsed as+            --+            -- (Note …+            --   (Let x …+            --     (Let y …+            --       (Note …+            --         (Let z …+            return (Dhall.Syntax.wrapInLets as b)++        alternative3 = do+            cs <- try (_forall <* whitespace <* _openParens)+            whitespace+            a <- label+            whitespace+            _colon+            nonemptyWhitespace+            b <- expression+            whitespace+            _closeParens+            whitespace+            cs' <- _arrow+            whitespace+            c <- expression+            return (Pi (Just (cs <> cs')) a b c)++        alternative4 = do+            try (_assert *> whitespace *> _colon)+            nonemptyWhitespace+            a <- expression+            return (Assert a)++        alternative5 = do+            (a0Info, a0) <- applicationExpressionWithInfo++            let (parseFirstOperatorExpression, parseOperatorExpression) =+                    operatorExpression (pure a0)++            let alternative5A = do+                    case a0Info of+                        ImportExpr -> return ()+                        _          -> empty++                    bs <- some (do+                        try (nonemptyWhitespace *> _with *> nonemptyWhitespace)++                        let withComponent =+                                    fmap WithLabel anyLabelOrSome+                                <|> fmap (\_ -> WithQuestion) (text "?")++                        keys <- Combinators.NonEmpty.sepBy1 withComponent (try (whitespace *> _dot) *> whitespace)++                        whitespace++                        _equal++                        whitespace++                        value <- parseOperatorExpression++                        return (\e -> With e keys value) )++                    return (foldl (\e f -> f e) a0 bs)++            let alternative5B = do+                    a <- parseFirstOperatorExpression++                    whitespace++                    let alternative5B0 = do+                            cs <- _arrow+                            whitespace+                            b <- expression+                            whitespace+                            return (Pi (Just cs) "_" a b)++                    let alternative5B1 = do+                            _colon+                            nonemptyWhitespace+                            case (shallowDenote a, a0Info) of+                                (ListLit Nothing [], _) -> do+                                    b <- expression++                                    return (ListLit (Just b) [])+                                (Merge c d Nothing, NakedMergeOrSomeOrToMap) -> do+                                    b <- expression++                                    return (Merge c d (Just b))+                                (ToMap c Nothing, NakedMergeOrSomeOrToMap) -> do+                                    b <- expression++                                    return (ToMap c (Just b))+                                _ -> do+                                    b <- expression++                                    return (Annot a b)++                    let alternative5B2 =+                            case shallowDenote a of+                                ListLit Nothing [] ->+                                    fail "Empty list literal without annotation"+                                _ -> pure a++                    alternative5B0 <|> alternative5B1 <|> alternative5B2++            alternative5A <|> alternative5B++    -- The firstApplicationExpression argument is necessary in order to+    -- left-factor the parsers for function types and @with@ expressions to+    -- minimize backtracking+    --+    -- For a longer explanation, see:+    --+    -- https://github.com/dhall-lang/dhall-haskell/pull/1770#discussion_r419022486+    operatorExpression firstApplicationExpression =+        foldr cons nil operatorParsers+      where+        cons operatorParser (p0, p) =+            ( makeOperatorExpression p0 operatorParser p+            , makeOperatorExpression p  operatorParser p+            )++        nil = (firstApplicationExpression, applicationExpression)++    makeOperatorExpression firstSubExpression operatorParser subExpression = do+            a <- firstSubExpression++            bs <- Text.Megaparsec.many $ do+                (Src _ _ textOp, op0) <- srcAnd (try (whitespace *> operatorParser))++                r0 <- subExpression++                let l@(Note (Src startL _ textL) _) `op` r@(Note (Src _ endR textR) _) =+                        Note (Src startL endR (textL <> textOp <> textR)) (l `op0` r)+                    -- We shouldn't hit this branch if things are working, but+                    -- that is not enforced in the types+                    l `op` r =+                        l `op0` r++                return (`op` r0)++            return (foldl' (\x f -> f x) a bs)++    operatorParsers :: [Parser (Expr s a -> Expr s a -> Expr s a)]+    operatorParsers =+        [ Equivalent . Just           <$> _equivalent   <* whitespace+        , ImportAlt                   <$ _importAlt     <* nonemptyWhitespace+        , BoolOr                      <$ _or            <* whitespace+        , NaturalPlus                 <$ _plus          <* nonemptyWhitespace+        , TextAppend                  <$ _textAppend    <* whitespace+        , ListAppend                  <$ _listAppend    <* whitespace+        , BoolAnd                     <$ _and           <* whitespace+        , (\cs -> Combine (Just cs) Nothing)         <$> _combine <* whitespace+        , (\cs -> Prefer (Just cs) PreferFromSource) <$> _prefer  <* whitespace+        , CombineTypes . Just         <$> _combineTypes <* whitespace+        , NaturalTimes                <$ _times         <* whitespace+        -- Make sure that `==` is not actually the prefix of `===`+        , BoolEQ                      <$ try (_doubleEqual <* Text.Megaparsec.notFollowedBy (char '=')) <* whitespace+        , BoolNE                      <$ _notEqual      <* whitespace+        ]++    applicationExpression = snd <$> applicationExpressionWithInfo++    applicationExpressionWithInfo :: Parser (ApplicationExprInfo, Expr Src a)+    applicationExpressionWithInfo = do+            let alternative0 = do+                    try (_merge *> nonemptyWhitespace)++                    a <- importExpression_ <* nonemptyWhitespace++                    return (\b -> Merge a b Nothing, Just "second argument to ❰merge❱")++            let alternative1 = do+                    try (_Some *> nonemptyWhitespace)++                    return (Some, Just "argument to ❰Some❱")++            let alternative2 = do+                    try (_toMap *> nonemptyWhitespace)++                    return (\a -> ToMap a Nothing, Just "argument to ❰toMap❱")++            let alternative3 = do+                    try (_showConstructor *> nonemptyWhitespace)++                    return (\a -> ShowConstructor a, Just "argument to ❰showConstructor❱")++            let alternative4 =+                    return (id, Nothing)++            (f, maybeMessage) <- alternative0 <|> alternative1 <|> alternative2 <|> alternative3 <|> alternative4++            let adapt parser =+                    case maybeMessage of+                        Nothing      -> parser+                        Just message -> parser <?> message++            a <- adapt (noted importExpression_)++            bs <- Text.Megaparsec.many . try $ do+                (sep, _) <- Text.Megaparsec.match nonemptyWhitespace+                b <- importExpression_+                return (sep, b)++            let c = foldl' app (f a) bs++            let info =+                    case (maybeMessage, bs) of+                        (Just _ , []) -> NakedMergeOrSomeOrToMap+                        (Nothing, []) -> ImportExpr+                        _             -> ApplicationExpr++            return (info, c)+          where+            app a (sep, b)+                | Note (Src left _ bytesL) _ <- a+                , Note (Src _ right bytesR) _ <- b+                = Note (Src left right (bytesL <> sep <> bytesR)) (App a b)+            app a (_, b) =+                App a b++    importExpression_ = noted (choice [ alternative0, alternative1 ])+          where+            alternative0 = do+                a <- embedded+                return (Embed a)++            alternative1 = completionExpression++    completionExpression = noted (do+        a <- selectorExpression++        mb <- optional (do+            try (whitespace *> _doubleColon)++            whitespace++            selectorExpression )++        case mb of+            Nothing -> return a+            Just b  -> return (RecordCompletion a b) )++    selectorExpression = noted (do+            a <- primitiveExpression++            let recordType = _openParens *> whitespace *> expression <* whitespace <* _closeParens++            let field               x  e = Field   e  x+            let projectBySet        xs e = Project e (Left  xs)+            let projectByExpression xs e = Project e (Right xs)++            let alternatives = do+                    src0 <- src whitespace++                    let fieldSelection = do+                            l <- anyLabel++                            pos <- Text.Megaparsec.getSourcePos++                            -- FIXME: Suffix whitespace can't be parsed given our limitation+                            -- about whitespace treatment, but for @dhall-docs@ this+                            -- is enough+                            let src1 = Src pos pos ""++                            return (FieldSelection (Just src0) l (Just src1))++                    let result =+                                fmap field               fieldSelection+                            <|> fmap projectBySet        labels+                            <|> fmap projectByExpression recordType++                    result++            b <- Text.Megaparsec.many (try (whitespace *> _dot *> alternatives))++            return (foldl' (\e k -> k e) a b) )++    primitiveExpression =+            noted+                ( choice+                    [ bytesLiteral+                    , temporalLiteral+                    , alternative00+                    , alternative01+                    , alternative02+                    , textLiteral+                    , alternative04+                    , unionType+                    , listLiteral+                    , alternative37+                    , alternative09+                    , builtin+                    ]+                )+            <|> alternative38+          where+            alternative00 = do+                n <- getOffset+                a <- try doubleLiteral+                b <- if isInfinite a+                       then setOffset n *> fail "double out of bounds"+                       else return a+                return (DoubleLit (DhallDouble b))++            alternative01 = do+                a <- try naturalLiteral+                return (NaturalLit a)++            alternative02 = do+                a <- try integerLiteral+                return (IntegerLit a)++            alternative04 = (do+                _openBrace++                src0 <- src whitespace+                mComma <- optional _comma++                -- `src1` corresponds to the prefix whitespace of the first key-value+                -- pair. This is done to avoid using `try` to recover the consumed+                -- whitespace when the comma is not consumed+                src1 <- case mComma of+                    Nothing -> return src0+                    Just _ -> src whitespace++                a <- recordTypeOrLiteral src1++                _closeBrace++                return a ) <?> "literal"++            alternative09 = do+                a <- try doubleInfinity+                return (DoubleLit (DhallDouble a))++            builtin = do+                let predicate c =+                            c == 'N'+                        ||  c == 'I'+                        ||  c == 'D'+                        ||  c == 'L'+                        ||  c == 'O'+                        ||  c == 'B'+                        ||  c == 'S'+                        ||  c == 'T'+                        ||  c == 'F'+                        ||  c == 'K'++                let nan = DhallDouble (0.0/0.0)++                c <- Text.Megaparsec.lookAhead (Text.Megaparsec.satisfy predicate)++                case c of+                    'N' ->+                        choice+                            [ NaturalFold      <$ _NaturalFold+                            , NaturalBuild     <$ _NaturalBuild+                            , NaturalIsZero    <$ _NaturalIsZero+                            , NaturalEven      <$ _NaturalEven+                            , NaturalOdd       <$ _NaturalOdd+                            , NaturalSubtract  <$ _NaturalSubtract+                            , NaturalToInteger <$ _NaturalToInteger+                            , NaturalShow      <$ _NaturalShow+                            , Natural          <$ _Natural+                            , None             <$ _None+                            , DoubleLit nan    <$ _NaN+                            ]+                    'I' ->+                        choice+                            [ IntegerClamp     <$ _IntegerClamp+                            , IntegerNegate    <$ _IntegerNegate+                            , IntegerShow      <$ _IntegerShow+                            , IntegerToDouble  <$ _IntegerToDouble+                            , Integer          <$ _Integer+                            ]++                    'D' ->+                        choice+                            [ DateShow         <$ _DateShow+                            , Date             <$ _Date+                            , DoubleShow       <$ _DoubleShow+                            , Double           <$ _Double+                            ]+                    'L' ->+                        choice+                            [ ListBuild        <$ _ListBuild+                            , ListFold         <$ _ListFold+                            , ListLength       <$ _ListLength+                            , ListHead         <$ _ListHead+                            , ListLast         <$ _ListLast+                            , ListIndexed      <$ _ListIndexed+                            , ListReverse      <$ _ListReverse+                            , List             <$ _List+                            ]+                    'O' ->    Optional         <$ _Optional+                    'B' ->+                        choice+                            [ Bool             <$ _Bool+                            , Bytes            <$ _Bytes+                            ]+                    'S' ->    Const Sort       <$ _Sort+                    'T' ->+                        choice+                            [ TextReplace      <$ _TextReplace+                            , TextShow         <$ _TextShow+                            , Text             <$ _Text+                            , TimeZoneShow     <$ _TimeZoneShow+                            , TimeZone         <$ _TimeZone+                            , TimeShow         <$ _TimeShow+                            , Time             <$ _Time+                            , BoolLit True     <$ _True+                            , Const Type       <$ _Type+                            ]+                    'F' ->    BoolLit False    <$ _False+                    'K' ->    Const Kind       <$ _Kind+                    _   ->    empty++            alternative37 = do+                a <- identifier+                return (Var a)++            alternative38 = do+                _openParens+                whitespace+                a <- expression+                whitespace+                _closeParens+                return a++    doubleQuotedChunk =+            choice+                [ interpolation+                , unescapedCharacterFast+                , unescapedCharacterSlow+                , escapedCharacter+                ]+          where+            interpolation = do+                _ <- text "${"+                e <- completeExpression_+                _ <- char '}'+                return (Chunks [(mempty, e)] mempty)++            unescapedCharacterFast = do+                t <- Text.Megaparsec.takeWhile1P Nothing predicate+                return (Chunks [] t)+              where+                predicate c =+                    (   ('\x20' <= c && c <= '\x21'    )+                    ||  ('\x23' <= c && c <= '\x5B'    )+                    ||  ('\x5D' <= c && c <= '\x10FFFF')+                    ) && c /= '$'++            unescapedCharacterSlow = do+                _ <- char '$'+                return (Chunks [] "$")++            escapedCharacter = do+                _ <- char '\\'+                c <- choice+                    [ quotationMark+                    , dollarSign+                    , backSlash+                    , forwardSlash+                    , backSpace+                    , formFeed+                    , lineFeed+                    , carriageReturn+                    , tab+                    , unicode+                    ]+                return (Chunks [] (Data.Text.singleton c))+              where+                quotationMark = char '"'++                dollarSign = char '$'++                backSlash = char '\\'++                forwardSlash = char '/'++                backSpace = do _ <- char 'b'; return '\b'++                formFeed = do _ <- char 'f'; return '\f'++                lineFeed = do _ <- char 'n'; return '\n'++                carriageReturn = do _ <- char 'r'; return '\r'++                tab = do _ <- char 't'; return '\t'++                unicode = do+                    _  <- char 'u';++                    let toNumber = Data.List.foldl' (\x y -> x * 16 + y) 0++                    let fourCharacterEscapeSequence = do+                            ns <- Control.Monad.replicateM 4 hexNumber++                            let number = toNumber ns++                            Control.Monad.guard (validCodepoint number)+                                <|> fail "Invalid Unicode code point"++                            return number++                    let bracedEscapeSequence = do+                            _  <- char '{'+                            ns <- some hexNumber++                            let number = toNumber ns++                            Control.Monad.guard (number <= 0x10FFFD && validCodepoint number)+                                <|> fail "Invalid Unicode code point"++                            _  <- char '}'++                            return number++                    n <- bracedEscapeSequence <|> fourCharacterEscapeSequence++                    return (Char.chr n)++    doubleQuotedLiteral = do+            _      <- char '"'+            chunks <- Text.Megaparsec.many doubleQuotedChunk+            _      <- char '"'+            return (mconcat chunks)++    singleQuoteContinue =+            choice+                [ escapeSingleQuotes+                , interpolation+                , escapeInterpolation+                , endLiteral+                , unescapedCharacterFast+                , unescapedCharacterSlow+                , tab+                , endOfLine_+                ]+          where+                escapeSingleQuotes = do+                    _ <- "'''" :: Parser Text+                    b <- singleQuoteContinue+                    return ("''" <> b)++                interpolation = do+                    _ <- text "${"+                    a <- completeExpression_+                    _ <- char '}'+                    b <- singleQuoteContinue+                    return (Chunks [(mempty, a)] mempty <> b)++                escapeInterpolation = do+                    _ <- text "''${"+                    b <- singleQuoteContinue+                    return ("${" <> b)++                endLiteral = do+                    _ <- text "''"+                    return mempty++                unescapedCharacterFast = do+                    a <- Text.Megaparsec.takeWhile1P Nothing predicate+                    b <- singleQuoteContinue+                    return (Chunks [] a <> b)+                  where+                    predicate c =+                        ('\x20' <= c && c <= '\x10FFFF') && c /= '$' && c /= '\''++                unescapedCharacterSlow = do+                    a <- satisfy predicate+                    b <- singleQuoteContinue+                    return (Chunks [] a <> b)+                  where+                    predicate c = c == '$' || c == '\''++                endOfLine_ = do+                    a <- "\n" <|> "\r\n"+                    b <- singleQuoteContinue+                    return (Chunks [] a <> b)++                tab = do+                    _ <- char '\t' <?> "tab"+                    b <- singleQuoteContinue+                    return ("\t" <> b)++    singleQuoteLiteral = do+            _ <- text "''"++            _ <- endOfLine++            a <- singleQuoteContinue++            return (Dhall.Syntax.toDoubleQuoted a)++    textLiteral = (do+        literal <- doubleQuotedLiteral <|> singleQuoteLiteral+        return (TextLit literal) ) <?> "literal"++    bytesLiteral = (do+        _ <- text "0x\""++        let byte = do+                nibble0 <- Text.Megaparsec.satisfy hexdig+                nibble1 <- Text.Megaparsec.satisfy hexdig+                return ([nibble0, nibble1] `base` 16)++        bytes <- Text.Megaparsec.many byte++        _ <- char '"'++        return (BytesLit (ByteString.pack bytes)) ) <?> "literal"++    recordTypeOrLiteral firstSrc0 =+            choice+                [ emptyRecordLiteral+                , nonEmptyRecordTypeOrLiteral firstSrc0+                , emptyRecordType+                ]++    emptyRecordLiteral = do+        _equal++        _ <- optional (try (whitespace *> _comma))++        whitespace+        return (RecordLit mempty)++    emptyRecordType = return (Record mempty)++    nonEmptyRecordTypeOrLiteral firstSrc0 = do+            let nonEmptyRecordType = do+                    (firstKeySrc1, a) <- try $ do+                        a <- anyLabelOrSome+                        s <- src whitespace+                        _colon+                        return (s, a)++                    firstKeySrc2 <- src nonemptyWhitespace++                    b <- expression++                    e <- Text.Megaparsec.many $ do+                        (src0', c) <- try $ do+                            _comma+                            src0' <- src whitespace+                            c <- anyLabelOrSome+                            return (src0', c)++                        src1 <- src whitespace++                        _colon++                        src2 <- src nonemptyWhitespace++                        d <- expression++                        whitespace++                        return (c, RecordField (Just src0') d (Just src1) (Just src2))++                    _ <- optional (whitespace *> _comma)+                    whitespace++                    m <- toMap ((a, RecordField (Just firstSrc0) b (Just firstKeySrc1) (Just firstKeySrc2)) : e)++                    return (Record m)++            let keysValue maybeSrc = do+                    firstSrc0' <- case maybeSrc of+                        Just src0 -> return src0+                        Nothing -> src whitespace+                    firstLabel <- anyLabelOrSome+                    firstSrc1 <- src whitespace++                    let parseLabelWithWhsp = try $ do+                            _dot+                            src0 <- src whitespace+                            l <- anyLabelOrSome+                            src1 <- src whitespace+                            return (src0, l, src1)++                    restKeys <- Combinators.many parseLabelWithWhsp+                    let keys = (firstSrc0', firstLabel, firstSrc1) :| restKeys++                    let normalRecordEntry = do+                            try _equal++                            lastSrc2 <- src whitespace++                            value <- expression++                            let cons (s0, key, s1) (key', values) =+                                    (key, RecordField (Just s0) (RecordLit [ (key', values) ]) (Just s1) Nothing)++                            let (lastSrc0, lastLabel, lastSrc1) = NonEmpty.last keys+                            let nil = (lastLabel, RecordField (Just lastSrc0) value (Just lastSrc1) (Just lastSrc2))++                            return (foldr cons nil (NonEmpty.init keys))++                    let punnedEntry =+                            case keys of+                                (s0, x, s1) :| [] -> return (x, RecordField (Just s0) (Var (V x 0)) (Just s1) Nothing)+                                _       -> empty++                    (normalRecordEntry <|> punnedEntry) <* whitespace++            let nonEmptyRecordLiteral = do+                    a <- keysValue (Just firstSrc0)++                    as <- many (try (_comma *> keysValue Nothing))++                    _ <- optional (whitespace *> _comma)++                    whitespace++                    let combine k = liftA2 $ \rf rf' -> makeRecordField $ Combine mempty (Just k)+                                                            (recordFieldValue rf')+                                                            (recordFieldValue rf)++                    m <- toMapWith combine (a : as)++                    return (RecordLit m)++            nonEmptyRecordType <|> nonEmptyRecordLiteral++    unionType = (do+            _openAngle++            whitespace++            let unionTypeEntry = do+                    a <- anyLabelOrSome++                    whitespace++                    b <- optional (_colon *> nonemptyWhitespace *> expression <* whitespace)++                    return (a, b)++            let nonEmptyUnionType = do+                    kv <- try (optional (_bar *> whitespace) *> unionTypeEntry)++                    kvs <- many (try (_bar *> whitespace *> unionTypeEntry))++                    m <- toMap (kv : kvs)++                    _ <- optional (_bar *> whitespace)++                    _closeAngle++                    return (Union m)++            let emptyUnionType = do+                    try (optional (_bar *> whitespace) *> _closeAngle)++                    return (Union mempty)++            nonEmptyUnionType <|> emptyUnionType ) <?> "literal"++    listLiteral = (do+            _openBracket++            whitespace++            let nonEmptyListLiteral = do+                    a <- try (optional (_comma *> whitespace) *> expression)++                    whitespace++                    as <- many (try (_comma *> whitespace *> expression) <* whitespace)++                    _ <- optional (_comma *> whitespace)++                    _closeBracket++                    return (ListLit Nothing (Data.Sequence.fromList (a : as)))++            let emptyListLiteral = do+                    try (optional (_comma *> whitespace) *> _closeBracket)++                    return (ListLit Nothing mempty)++            nonEmptyListLiteral <|> emptyListLiteral) <?> "literal"++{-| Parse an environment variable import++    This corresponds to the @env@ rule from the official grammar+-}+env :: Parser ImportType+env = do+    _ <- text "env:"+    a <- (alternative0 <|> alternative1)+    return (Env a)+  where+    alternative0 = bashEnvironmentVariable++    alternative1 = do+        _ <- char '"'+        a <- posixEnvironmentVariable+        _ <- char '"'+        return a++-- | Parse a local import without trailing whitespace+localOnly :: Parser ImportType+localOnly =+    choice+        [ parentPath+        , herePath+        , homePath+        , try absolutePath+        ]+  where+    parentPath = do+        _    <- ".." :: Parser Text+        file <- file_ FileComponent++        return (Local Parent file)++    herePath = do+        _    <- "." :: Parser Text+        file <- file_ FileComponent++        return (Local Here file)++    homePath = do+        _    <- "~" :: Parser Text+        file <- file_ FileComponent++        return (Local Home file)++    absolutePath = do+        file <- file_ FileComponent++        return (Local Absolute file)++{-| Parse a local import++    This corresponds to the @local@ rule from the official grammar+-}+local :: Parser ImportType+local = do+    a <- localOnly+    return a++{-| Parse an HTTP(S) import++    This corresponds to the @http@ rule from the official grammar+-}+http :: Parser ImportType+http = do+    url <- httpRaw+    headers <- optional (do+        try (whitespace *> _using *> nonemptyWhitespace)+        importExpression import_ )+    return (Remote (url { headers }))++{-| Parse a `Missing` import++    This corresponds to the @missing@ rule from the official grammar+-}+missing :: Parser ImportType+missing = do+  _missing+  return Missing++{-| Parse an `ImportType`++    This corresponds to the @import-type@ rule from the official grammar+-}+importType_ :: Parser ImportType+importType_ = do+    let predicate c =+            c == '~' || c == '.' || c == '/' || c == 'h' || c == 'e' || c == 'm'++    _ <- Text.Megaparsec.lookAhead (Text.Megaparsec.satisfy predicate)++    choice [ local, http, env, missing ]++{-| Parse a `Dhall.Crypto.SHA256Digest`++    This corresponds to the @hash@ rule from the official grammar+-}+importHash_ :: Parser Dhall.Crypto.SHA256Digest+importHash_ = do+    _ <- text "sha256:"+    t <- count 64 (satisfy hexdig <?> "hex digit")+    let strictBytes16 = Data.Text.Encoding.encodeUtf8 t+    strictBytes <- case Base16.decode strictBytes16 of+        Left  string      -> fail string+        Right strictBytes -> return strictBytes+    case Dhall.Crypto.sha256DigestFromByteString strictBytes of+      Nothing -> fail "Invalid sha256 hash"+      Just h  -> pure h++{-| Parse an `ImportHashed`++    This corresponds to the @import-hashed@ rule from the official grammar+-}+importHashed_ :: Parser ImportHashed+importHashed_ = do+    importType <- importType_+    hash       <- optional (try (nonemptyWhitespace *> importHash_))+    return (ImportHashed {..})++{-| Parse an `Import`++    This corresponds to the @import@ rule from the official grammar+-}+import_ :: Parser Import+import_ = (do+    importHashed <- importHashed_+    importMode   <- alternative <|> pure Code+    return (Import {..}) ) <?> "import"+  where+    alternative = do+      try (whitespace *> _as *> nonemptyWhitespace)++      (_Text >> pure RawText)+          <|> (_Location >> pure Location)+          <|> (_Bytes >> pure RawBytes)++-- | 'ApplicationExprInfo' distinguishes certain subtypes of application+-- expressions.+data ApplicationExprInfo+    = NakedMergeOrSomeOrToMap+    -- ^ @merge x y@, @Some x@ or @toMap x@, unparenthesized.+    | ImportExpr+    -- ^ An import expression.+    | ApplicationExpr+    -- ^ Any other application expression.
src/Dhall/Parser/Token.hs view
@@ -1,790 +1,1438 @@-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE OverloadedStrings #-}--- | 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 (-    whitespace,-    bashEnvironmentVariable,-    posixEnvironmentVariable,-    ComponentType(..),-    file_,-    label,-    anyLabel,-    labels,-    httpRaw,-    hexdig,-    identifier,-    hexNumber,-    doubleLiteral,-    doubleInfinity,-    naturalLiteral,-    integerLiteral,-    _Optional,-    _if,-    _then,-    _else,-    _let,-    _in,-    _as,-    _using,-    _merge,-    _constructors,-    _Some,-    _None,-    _NaturalFold,-    _NaturalBuild,-    _NaturalIsZero,-    _NaturalEven,-    _NaturalOdd,-    _NaturalToInteger,-    _NaturalShow,-    _IntegerShow,-    _IntegerToDouble,-    _DoubleShow,-    _ListBuild,-    _ListFold,-    _ListLength,-    _ListHead,-    _ListLast,-    _ListIndexed,-    _ListReverse,-    _OptionalFold,-    _OptionalBuild,-    _Bool,-    _Natural,-    _Integer,-    _Double,-    _Text,-    _TextShow,-    _List,-    _True,-    _False,-    _NaN,-    _Type,-    _Kind,-    _Sort,-    _equal,-    _or,-    _plus,-    _textAppend,-    _listAppend,-    _and,-    _times,-    _doubleEqual,-    _notEqual,-    _dot,-    _openBrace,-    _closeBrace,-    _openBracket,-    _closeBracket,-    _openAngle,-    _closeAngle,-    _bar,-    _comma,-    _openParens,-    _closeParens,-    _colon,-    _at,-    _missing,-    _importAlt,-    _combine,-    _combineTypes,-    _prefer,-    _lambda,-    _forall,-    _arrow,-    ) where--import           Dhall.Parser.Combinators--import Control.Applicative (Alternative(..), optional)-import Data.Functor (void)-import Data.Semigroup (Semigroup(..))-import Data.Text (Text)-import Dhall.Core-import Dhall.Set (Set)-import Prelude hiding (const, pi)-import Text.Parser.Combinators (choice, try, (<?>))--import qualified Control.Monad-import qualified Data.Char-import qualified Data.HashSet-import qualified Data.List.NonEmpty-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.Combinators--import Numeric.Natural (Natural)-import Prelude hiding (const, pi)--import qualified Text.Parser.Token---whitespace :: Parser ()-whitespace = Text.Parser.Combinators.skipMany whitespaceChunk--nonemptyWhitespace :: Parser ()-nonemptyWhitespace = Text.Parser.Combinators.skipSome whitespaceChunk--alpha :: Char -> Bool-alpha c = ('\x41' <= c && c <= '\x5A') || ('\x61' <= c && c <= '\x7A')--digit :: Char -> Bool-digit c = '\x30' <= c && c <= '\x39'--hexdig :: Char -> Bool-hexdig c =-        ('0' <= c && c <= '9')-    ||  ('A' <= c && c <= 'F')-    ||  ('a' <= c && c <= 'f')--signPrefix :: Num a => Parser (a -> a)-signPrefix = (do-    let positive = fmap (\_ -> id    ) (Text.Parser.Char.char '+')-    let negative = fmap (\_ -> negate) (Text.Parser.Char.char '-')-    positive <|> negative ) <?> "sign"--doubleLiteral :: Parser Double-doubleLiteral = (do-    sign <- signPrefix <|> pure id-    a <- Text.Parser.Token.double-    return (sign a) ) <?> "double literal"--doubleInfinity :: Parser Double-doubleInfinity = (do-    let negative = fmap (\_ -> negate) (Text.Parser.Char.char '-')-    sign <- negative <|> pure id-    a <- Text.Parser.Char.text "Infinity" >> whitespace >> return (1.0/0.0)-    return (sign a) ) <?> "double infinity"--integerLiteral :: Parser Integer-integerLiteral = (do-    sign <- signPrefix-    a <- Text.Megaparsec.Char.Lexer.decimal-    whitespace-    return (sign a) ) <?> "integer literal"--naturalLiteral :: Parser Natural-naturalLiteral = (do-    a <- Text.Megaparsec.Char.Lexer.decimal-    whitespace-    return a ) <?> "natural literal"--identifier :: Parser Var-identifier = do-    x <- label--    let indexed = do-            _ <- Text.Parser.Char.char '@'-            n <- Text.Megaparsec.Char.Lexer.decimal-            whitespace-            return n--    n <- indexed <|> pure 0-    return (V x n)--whitespaceChunk :: Parser ()-whitespaceChunk =-    choice-        [ void (Dhall.Parser.Combinators.takeWhile1 predicate)-        , void (Text.Parser.Char.text "\r\n")-        , lineComment-        , blockComment-        ] <?> "whitespace"-  where-    predicate c = c == ' ' || c == '\t' || c == '\n'--hexNumber :: Parser Int-hexNumber = choice [ hexDigit, hexUpper, hexLower ]-  where-    hexDigit = do-        c <- Text.Parser.Char.satisfy predicate-        return (Data.Char.ord c - Data.Char.ord '0')-      where-        predicate c = '0' <= c && c <= '9'--    hexUpper = do-        c <- Text.Parser.Char.satisfy predicate-        return (10 + Data.Char.ord c - Data.Char.ord 'A')-      where-        predicate c = 'A' <= c && c <= 'F'--    hexLower = do-        c <- Text.Parser.Char.satisfy predicate-        return (10 + Data.Char.ord c - Data.Char.ord 'a')-      where-        predicate c = 'a' <= c && c <= 'f'--lineComment :: Parser ()-lineComment = do-    _ <- Text.Parser.Char.text "--"--    let predicate c = ('\x20' <= c && c <= '\x10FFFF') || c == '\t'--    _ <- Dhall.Parser.Combinators.takeWhile predicate--    endOfLine--    return ()-  where-    endOfLine =-            void (Text.Parser.Char.char '\n'  )-        <|> void (Text.Parser.Char.text "\r\n")--blockComment :: Parser ()-blockComment = do-    _ <- Text.Parser.Char.text "{-"-    blockCommentContinue--blockCommentChunk :: Parser ()-blockCommentChunk =-    choice-        [ blockComment  -- Nested block comment-        , characters-        , character-        , endOfLine-        ]-  where-    characters = void (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)-      where-        predicate c = '\x20' <= c && c <= '\x10FFFF' || c == '\n' || c == '\t'--    endOfLine = void (Text.Parser.Char.text "\r\n")--blockCommentContinue :: Parser ()-blockCommentContinue = endOfComment <|> continue-  where-    endOfComment = void (Text.Parser.Char.text "-}")--    continue = do-        blockCommentChunk-        blockCommentContinue--simpleLabel :: Bool -> Parser Text-simpleLabel allowReserved = try (do-    c    <- Text.Parser.Char.satisfy headCharacter-    rest <- Dhall.Parser.Combinators.takeWhile tailCharacter-    let text = Data.Text.cons c rest-    Control.Monad.guard (allowReserved || not (Data.HashSet.member text reservedIdentifiers))-    return text )-  where-    headCharacter c = alpha c || c == '_'--    tailCharacter c = alpha c || digit c || c == '_' || c == '-' || c == '/'--backtickLabel :: Parser Text-backtickLabel = do-    _ <- Text.Parser.Char.char '`'-    t <- takeWhile1 predicate-    _ <- Text.Parser.Char.char '`'-    return t-  where-    predicate c =-            '\x20' <= c && c <= '\x5F'-        ||  '\x61' <= c && c <= '\x7E'--labels :: Parser (Set Text)-labels = do-    _openBrace-    xs <- nonEmptyLabels <|> emptyLabels-    _closeBrace-    return xs-  where-    emptyLabels = pure Dhall.Set.empty--    nonEmptyLabels = do-        x  <- anyLabel-        xs <- many (do _ <- _comma; anyLabel)-        noDuplicates (x : xs)---label :: Parser Text-label = (do-    t <- backtickLabel <|> simpleLabel False-    whitespace-    return t ) <?> "label"--anyLabel :: Parser Text-anyLabel = (do-    t <- backtickLabel <|> simpleLabel True-    whitespace-    return t ) <?> "any label"--bashEnvironmentVariable :: Parser Text-bashEnvironmentVariable = satisfy predicate0 <> star (satisfy predicate1)-  where-    predicate0 c = alpha c || c == '_'--    predicate1 c = alpha c || digit c || c == '_'--posixEnvironmentVariable :: Parser Text-posixEnvironmentVariable = plus posixEnvironmentVariableCharacter--posixEnvironmentVariableCharacter :: Parser Text-posixEnvironmentVariableCharacter =-    escapeCharacter <|> satisfy predicate1-  where-    escapeCharacter = do-        _ <- Text.Parser.Char.char '\\'--        c <- Text.Parser.Char.satisfy (`elem` ("\"\\abfnrtv" :: String))--        case c of-            '"'  -> return "\""-            '\\' -> return "\\"-            'a'  -> return "\a"-            'b'  -> return "\b"-            'f'  -> return "\f"-            'n'  -> return "\n"-            'r'  -> return "\r"-            't'  -> return "\t"-            'v'  -> return "\v"-            _    -> empty--    predicate1 c =-            ('\x20' <= c && c <= '\x21')-        ||  ('\x23' <= c && c <= '\x3C')-        ||  ('\x3E' <= c && c <= '\x5B')-        ||  ('\x5D' <= c && c <= '\x7E')--quotedPathCharacter :: Char -> Bool-quotedPathCharacter c =-        ('\x20' <= c && c <= '\x21')-    ||  ('\x23' <= c && c <= '\x2E')-    ||  ('\x30' <= c && c <= '\x10FFFF')--data ComponentType = URLComponent | FileComponent--pathComponent :: ComponentType -> Parser Text-pathComponent componentType = do-    _ <- "/" :: Parser Text--    let pathData = do-            text <- Text.Megaparsec.takeWhile1P Nothing Dhall.Core.pathCharacter--            case componentType of-                FileComponent -> return text-                URLComponent  -> return (URI.Encode.decodeText text)--    let quotedPathData = do-            _    <- Text.Parser.Char.char '"'-            text <- Text.Megaparsec.takeWhile1P Nothing quotedPathCharacter-            _    <- Text.Parser.Char.char '"'--            return text--    pathData <|> quotedPathData--file_ :: ComponentType -> Parser File-file_ componentType = do-    path <- Data.List.NonEmpty.some1 (pathComponent componentType)--    let directory = Directory (reverse (Data.List.NonEmpty.init path))-    let file      = Data.List.NonEmpty.last path--    return (File {..})--scheme_ :: Parser Scheme-scheme_ =-        ("http" :: Parser Text)-    *>  ((("s" :: Parser Text) *> pure HTTPS) <|> pure HTTP)-    <*  ("://" :: Parser Text)--httpRaw :: Parser URL-httpRaw = do-    scheme    <- scheme_-    authority <- authority_-    path      <- file_ URLComponent-    query     <- optional (("?" :: Parser Text) *> query_)--    let headers = Nothing--    return (URL {..})--authority_ :: Parser Text-authority_ = option (try (userinfo <> "@")) <> host <> option (":" <> port)--userinfo :: Parser Text-userinfo = star (satisfy predicate <|> pctEncoded)-  where-    predicate c = unreserved c || subDelims c || c == ':'--host :: Parser Text-host = choice [ ipLiteral, ipV4Address, regName ]--port :: Parser Text-port = star (satisfy digit)--ipLiteral :: Parser Text-ipLiteral = "[" <> (ipV6Address <|> ipVFuture) <> "]"--ipVFuture :: Parser Text-ipVFuture = "v" <> plus (satisfy hexdig) <> "." <> plus (satisfy predicate)-  where-    predicate c = unreserved c || subDelims c || c == ':'--ipV6Address :: Parser Text-ipV6Address =-    choice-        [ try alternative0-        , try alternative1-        , try alternative2-        , try alternative3-        , try alternative4-        , try alternative5-        , try alternative6-        , try alternative7-        ,     alternative8-        ]-  where-    alternative0 = count 6 (h16 <> ":") <> ls32--    alternative1 = "::" <> count 5 (h16 <> ":") <> ls32--    alternative2 = option h16 <> "::" <> count 4 (h16 <> ":") <> ls32--    alternative3 =-            option (h16 <> range 0 1 (try (":" <> h16)))-        <>  "::"-        <>  count 3 (h16 <> ":")-        <>  ls32--    alternative4 =-            option (h16 <> range 0 2 (try (":" <> h16)))-        <>  "::"-        <>  count 2 (h16 <> ":")-        <>  ls32--    alternative5 =-            option (h16 <> range 0 3 (try (":" <> h16)))-        <>  "::"-        <>  h16-        <>  ":"-        <>  ls32--    alternative6 =-        option (h16 <> range 0 4 (try (":" <> h16))) <> "::" <> ls32--    alternative7 =-        option (h16 <> range 0 5 (try (":" <> h16))) <> "::" <> h16--    alternative8 =-        option (h16 <> range 0 6 (try (":" <> h16))) <> "::"--h16 :: Parser Text-h16 = range 1 3 (satisfy hexdig)--ls32 :: Parser Text-ls32 = try (h16 <> ":" <> h16) <|> ipV4Address--ipV4Address :: Parser Text-ipV4Address = decOctet <> "." <> decOctet <> "." <> decOctet <> "." <> decOctet--decOctet :: Parser Text-decOctet =-    choice-        [ try alternative4-        , try alternative3-        , try alternative2-        , try alternative1-        ,     alternative0-        ]-  where-    alternative0 = satisfy digit--    alternative1 = satisfy predicate <> satisfy digit-      where-        predicate c = '\x31' <= c && c <= '\x39'--    alternative2 = "1" <> count 2 (satisfy digit)--    alternative3 = "2" <> satisfy predicate <> satisfy digit-      where-        predicate c = '\x30' <= c && c <= '\x34'--    alternative4 = "25" <> satisfy predicate-      where-        predicate c = '\x30' <= c && c <= '\x35'--regName :: Parser Text-regName = star (satisfy predicate <|> pctEncoded)-  where-    predicate c = unreserved c || subDelims c--pchar :: Parser Text-pchar = satisfy predicate <|> pctEncoded-  where-    predicate c = unreserved c || subDelims c || c == ':' || c == '@'--query_ :: Parser Text-query_ = star (pchar <|> satisfy predicate)-  where-    predicate c = c == '/' || c == '?'--pctEncoded :: Parser Text-pctEncoded = "%" <> count 2 (satisfy hexdig)--subDelims :: Char -> Bool-subDelims c = c `elem` ("!$&'()*+,;=" :: String)--unreserved :: Char -> Bool-unreserved c =-    alpha c || digit c || c == '-' || c == '.' || c == '_' || c == '~'--reserved :: Data.Text.Text -> Parser ()-reserved x = do _ <- Text.Parser.Char.text x; whitespace--reservedChar :: Char -> Parser ()-reservedChar c = do _ <- Text.Parser.Char.char c; whitespace--keyword :: Data.Text.Text -> Parser ()-keyword x = try (do _ <- Text.Parser.Char.text x; nonemptyWhitespace)--_if :: Parser ()-_if = keyword "if"--_then :: Parser ()-_then = keyword "then"--_else :: Parser ()-_else = keyword "else"--_let :: Parser ()-_let = keyword "let"--_in :: Parser ()-_in = keyword "in"--_as :: Parser ()-_as = keyword "as"--_using :: Parser ()-_using = keyword "using"--_merge :: Parser ()-_merge = keyword "merge"--_constructors :: Parser ()-_constructors = keyword "constructors"--_Some :: Parser ()-_Some = keyword "Some"--_None :: Parser ()-_None = reserved "None"--_NaturalFold :: Parser ()-_NaturalFold = reserved "Natural/fold"--_NaturalBuild :: Parser ()-_NaturalBuild = reserved "Natural/build"--_NaturalIsZero :: Parser ()-_NaturalIsZero = reserved "Natural/isZero"--_NaturalEven :: Parser ()-_NaturalEven = reserved "Natural/even"--_NaturalOdd :: Parser ()-_NaturalOdd = reserved "Natural/odd"--_NaturalToInteger :: Parser ()-_NaturalToInteger = reserved "Natural/toInteger"--_NaturalShow :: Parser ()-_NaturalShow = reserved "Natural/show"--_IntegerShow :: Parser ()-_IntegerShow = reserved "Integer/show"--_IntegerToDouble :: Parser ()-_IntegerToDouble = reserved "Integer/toDouble"--_DoubleShow :: Parser ()-_DoubleShow = reserved "Double/show"--_ListBuild :: Parser ()-_ListBuild = reserved "List/build"--_ListFold :: Parser ()-_ListFold = reserved "List/fold"--_ListLength :: Parser ()-_ListLength = reserved "List/length"--_ListHead :: Parser ()-_ListHead = reserved "List/head"--_ListLast :: Parser ()-_ListLast = reserved "List/last"--_ListIndexed :: Parser ()-_ListIndexed = reserved "List/indexed"--_ListReverse :: Parser ()-_ListReverse = reserved "List/reverse"--_OptionalFold :: Parser ()-_OptionalFold = reserved "Optional/fold"--_OptionalBuild :: Parser ()-_OptionalBuild = reserved "Optional/build"--_Bool :: Parser ()-_Bool = reserved "Bool"--_Optional :: Parser ()-_Optional = reserved "Optional"--_Natural :: Parser ()-_Natural = reserved "Natural"--_Integer :: Parser ()-_Integer = reserved "Integer"--_Double :: Parser ()-_Double = reserved "Double"--_Text :: Parser ()-_Text = reserved "Text"--_TextShow :: Parser ()-_TextShow = reserved "Text/show"--_List :: Parser ()-_List = reserved "List"--_True :: Parser ()-_True = reserved "True"--_False :: Parser ()-_False = reserved "False"--_NaN :: Parser ()-_NaN = reserved "NaN"--_Type :: Parser ()-_Type = reserved "Type"--_Kind :: Parser ()-_Kind = reserved "Kind"--_Sort :: Parser ()-_Sort = reserved "Sort"--_equal :: Parser ()-_equal = reservedChar '='--_or :: Parser ()-_or = reserved "||"--_plus :: Parser ()-_plus = reservedChar '+'--_textAppend :: Parser ()-_textAppend = reserved "++"--_listAppend :: Parser ()-_listAppend = reservedChar '#'--_and :: Parser ()-_and = reserved "&&"--_times :: Parser ()-_times = reservedChar '*'--_doubleEqual :: Parser ()-_doubleEqual = reserved "=="--_notEqual :: Parser ()-_notEqual = reserved "!="--_dot :: Parser ()-_dot = reservedChar '.'--_openBrace :: Parser ()-_openBrace = reservedChar '{'--_closeBrace :: Parser ()-_closeBrace = reservedChar '}'--_openBracket :: Parser ()-_openBracket = reservedChar '['--_closeBracket :: Parser ()-_closeBracket = reservedChar ']'--_openAngle :: Parser ()-_openAngle = reservedChar '<'--_closeAngle :: Parser ()-_closeAngle = reservedChar '>'--_bar :: Parser ()-_bar = reservedChar '|'--_comma :: Parser ()-_comma = reservedChar ','--_openParens :: Parser ()-_openParens = reservedChar '('--_closeParens :: Parser ()-_closeParens = reservedChar ')'--_colon :: Parser ()-_colon = reservedChar ':'--_at :: Parser ()-_at = reservedChar '@'--_missing :: Parser ()-_missing = reserved "missing"--_importAlt :: Parser ()-_importAlt = reservedChar '?'--_combine :: Parser ()-_combine = do-    void (Text.Parser.Char.char '∧' <?> "\"∧\"") <|> void (Text.Parser.Char.text "/\\")-    whitespace--_combineTypes :: Parser ()-_combineTypes = do-    void (Text.Parser.Char.char '⩓' <?> "\"⩓\"") <|> void (Text.Parser.Char.text "//\\\\")-    whitespace--_prefer :: Parser ()-_prefer = do-    void (Text.Parser.Char.char '⫽' <?> "\"⫽\"") <|> void (Text.Parser.Char.text "//")-    whitespace--_lambda :: Parser ()-_lambda = do-    _ <- Text.Parser.Char.satisfy predicate-    whitespace-  where-    predicate 'λ'  = True-    predicate '\\' = True-    predicate _    = False--_forall :: Parser ()-_forall = do-    void (Text.Parser.Char.char '∀' <?> "\"∀\"") <|> void (Text.Parser.Char.text "forall")-    whitespace--_arrow :: Parser ()-_arrow = do-    void (Text.Parser.Char.char '→' <?> "\"→\"") <|> void (Text.Parser.Char.text "->")-    whitespace+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards   #-}++-- | Parse Dhall tokens. Even though we don't have a tokenizer per-se this+---  module is useful for keeping some small parsing utilities.+module Dhall.Parser.Token (+    endOfLine,+    validCodepoint,+    whitespace,+    lineComment,+    lineCommentPrefix,+    blockComment,+    nonemptyWhitespace,+    bashEnvironmentVariable,+    posixEnvironmentVariable,+    ComponentType(..),+    text,+    char,+    file_,+    label,+    anyLabelOrSome,+    anyLabel,+    labels,+    httpRaw,+    hexdig,+    identifier,+    hexNumber,+    signPrefix,+    doubleLiteral,+    doubleInfinity,+    naturalLiteral,+    integerLiteral,+    dateFullYear,+    dateMonth,+    dateMday,+    timeHour,+    timeMinute,+    timeSecond,+    timeSecFrac,+    _Optional,+    _if,+    _then,+    _else,+    _let,+    _in,+    _as,+    _using,+    _merge,+    _toMap,+    _showConstructor,+    _assert,+    _Some,+    _None,+    _NaturalFold,+    _NaturalBuild,+    _NaturalIsZero,+    _NaturalEven,+    _NaturalOdd,+    _NaturalToInteger,+    _NaturalShow,+    _NaturalSubtract,+    _IntegerClamp,+    _IntegerNegate,+    _IntegerShow,+    _IntegerToDouble,+    _DoubleShow,+    _ListBuild,+    _ListFold,+    _ListLength,+    _ListHead,+    _ListLast,+    _ListIndexed,+    _ListReverse,+    _Bool,+    _Bytes,+    _Natural,+    _Integer,+    _Double,+    _Text,+    _TextReplace,+    _TextShow,+    _Date,+    _DateShow,+    _Time,+    _TimeShow,+    _TimeZone,+    _TimeZoneShow,+    _List,+    _True,+    _False,+    _NaN,+    _Type,+    _Kind,+    _Sort,+    _Location,+    _equal,+    _or,+    _plus,+    _textAppend,+    _listAppend,+    _and,+    _times,+    _doubleEqual,+    _notEqual,+    _dot,+    _openBrace,+    _closeBrace,+    _openBracket,+    _closeBracket,+    _openAngle,+    _closeAngle,+    _bar,+    _comma,+    _openParens,+    _closeParens,+    _colon,+    _at,+    _equivalent,+    _missing,+    _importAlt,+    _combine,+    _combineTypes,+    _prefer,+    _lambda,+    _forall,+    _arrow,+    _doubleColon,+    _with,+    ) where++import Dhall.Parser.Combinators++import Control.Applicative     (Alternative (..), optional)+import Data.Bits               ((.&.))+import Data.Fixed              (Pico)+import Data.Functor            (void, ($>))+import Data.Ratio              ((%))+import Data.Text               (Text)+import Dhall.Syntax+import Text.Parser.Combinators (choice, try, (<?>))++import qualified Control.Monad              as Monad+import qualified Data.Char                  as Char+import qualified Data.Foldable+import qualified Data.HashSet+import qualified Data.List                  as List+import qualified Data.List.NonEmpty+import qualified Data.Scientific            as Scientific+import qualified Data.Text+import qualified Text.Megaparsec+import qualified Text.Megaparsec.Char.Lexer+import qualified Text.Parser.Char+import qualified Text.Parser.Combinators+import qualified Text.Parser.Token++import Numeric.Natural (Natural)++-- | Match an end-of-line character sequence+endOfLine :: Parser Text+endOfLine =+    (   Text.Parser.Char.text "\n"  +    <|> Text.Parser.Char.text "\r\n"+    ) <?> "newline"++-- | Returns `True` if the given `Int` is a valid Unicode codepoint+validCodepoint :: Int -> Bool+validCodepoint c =+    not (category == Char.Surrogate+      || c .&. 0xFFFE == 0xFFFE+      || c .&. 0xFFFF == 0xFFFF)+  where+    category = Char.generalCategory (Char.chr c)++{-| Parse 0 or more whitespace characters (including comments)++    This corresponds to the @whsp@ rule in the official grammar+-}+whitespace :: Parser ()+whitespace = Text.Parser.Combinators.skipMany whitespaceChunk++{-| Parse 1 or more whitespace characters (including comments)++    This corresponds to the @whsp1@ rule in the official grammar+-}+nonemptyWhitespace :: Parser ()+nonemptyWhitespace = Text.Parser.Combinators.skipSome whitespaceChunk++alpha :: Char -> Bool+alpha c = ('\x41' <= c && c <= '\x5A') || ('\x61' <= c && c <= '\x7A')++digit :: Char -> Bool+digit c = '\x30' <= c && c <= '\x39'++alphaNum :: Char -> Bool+alphaNum c = alpha c || digit c++{-| Parse a hex digit (uppercase or lowercase)++    This corresponds to the @HEXDIG@ rule in the official grammar+-}+hexdig :: Char -> Bool+hexdig c =+        ('0' <= c && c <= '9')+    ||  ('A' <= c && c <= 'F')+    ||  ('a' <= c && c <= 'f')++-- | Parse a leading @+@ or @-@ sign+signPrefix :: Num a => Parser (a -> a)+signPrefix = (do+    let positive = fmap (\_ -> id    ) (char '+')+    let negative = fmap (\_ -> negate) (char '-')+    positive <|> negative ) <?> "sign"++{-| Parse a `Dhall.Syntax.Double` literal++    This corresponds to the @double-literal@ rule from the official grammar+-}+doubleLiteral :: Parser Double+doubleLiteral = (do+    -- We don't use `Text.Parser.Token.double` since that consumes trailing+    -- whitespace and there is no whitespace-free alternative.  See:+    --+    -- https://github.com/dhall-lang/dhall-haskell/pull/1646+    -- https://github.com/dhall-lang/dhall-haskell/pull/1647+    --+    -- We also don't use `Text.Megaparsec.Char.Lexer.float` because that+    -- transitively depends on `Data.Char.toTitle` which is broken on older+    -- versions of GHCJS that we still support.  See:+    --+    -- https://github.com/dhall-lang/dhall-haskell/pull/1681+    -- https://github.com/ghcjs/ghcjs-base/issues/62+    --+    -- Also, hand-writing the parser code for `Double` literals helps to better+    -- ensure that we follow the standard exactly as written.+    sign <- signPrefix <|> pure id++    x <- Text.Parser.Token.decimal++    let alternative0 = do+            y <- fraction++            e <- exponent' <|> pure 1++            return ((fromInteger x + y) * e)++    let alternative1 = do+            expo <- exponent'++            return (fromInteger x * expo)++    n <- alternative0 <|> alternative1++    return (sign (Scientific.toRealFloat n)) ) <?> "literal"+  where+    fraction = do+        _ <- Text.Parser.Char.char '.'++        digits <- some Text.Parser.Char.digit++        let snoc y d =+              y + Scientific.scientific (fromIntegral (Char.digitToInt d)) (Scientific.base10Exponent y - 1)++        return (List.foldl' snoc 0 digits)++    exponent' = do+        _ <- Text.Parser.Char.oneOf "eE"++        sign <- signPrefix <|> pure id++        x <- Text.Parser.Token.decimal++        return (Scientific.scientific 1 (fromInteger (sign x)))++{-| Parse a signed @Infinity@++    This corresponds to the @minus-infinity-literal@ and @plus-infinity-literal@+    rules from the official grammar+-}+doubleInfinity :: Parser Double+doubleInfinity = (do+    let negative = fmap (\_ -> negate) (char '-')+    sign <- negative <|> pure id+    a <- text "Infinity" >> return (1.0/0.0)+    return (sign a) ) <?> "literal"++{-| Parse an `Dhall.Syntax.Integer` literal++    This corresponds to the @integer-literal@ rule from the official grammar+-}+integerLiteral :: Parser Integer+integerLiteral = (do+    sign <- signPrefix+    a    <- naturalLiteral+    return (sign (fromIntegral a)) ) <?> "literal"++{-| Parse a `Dhall.Syntax.Natural` literal++    This corresponds to the @natural-literal@ rule from the official grammar+-}+naturalLiteral :: Parser Natural+naturalLiteral = (do+    a <-    binary+        <|> hexadecimal+        <|> decimal+        <|> (char '0' $> 0)+    return a ) <?> "literal"+  where+    binary = try (char '0' >> char 'b' >> Text.Megaparsec.Char.Lexer.binary)+    hexadecimal = try (char '0' >> char 'x' >> Text.Megaparsec.Char.Lexer.hexadecimal)+    decimal = do+        n <- headDigit+        ns <- many tailDigit+        return (mkNum (n:ns))+      where+        headDigit = decimalDigit nonZeroDigit <?> "non-zero digit"+          where+            nonZeroDigit c = '1' <= c && c <= '9'++        tailDigit = decimalDigit digit <?> "digit"++        decimalDigit predicate = do+            c <- Text.Parser.Char.satisfy predicate+            return (fromIntegral (Char.ord c - Char.ord '0'))++        mkNum = Data.Foldable.foldl' step 0+          where+            step acc x = acc * 10 + x++{-| Parse a 4-digit year++    This corresponds to the @date-fullyear@ rule from the official grammar+-}+dateFullYear :: Parser Integer+dateFullYear = do+    digits <- Monad.replicateM 4 (Text.Parser.Char.satisfy digit)++    return (digits `base` 10)++{-| Parse a 2-digit month++    This corresponds to the @date-month@ rule from the official grammar+-}+dateMonth :: Parser Int+dateMonth = do+    digits <- Monad.replicateM 2 (Text.Parser.Char.satisfy digit)++    let month = digits `base` 10++    if 1 <= month && month <= 12+        then return month+        else fail "Invalid month"++{-| Parse a 2-digit day of the month++    This corresponds to the @date-mday@ rule from the official grammar+-}+dateMday :: Parser Int+dateMday = do+    digits <- Monad.replicateM 2 (Text.Parser.Char.satisfy digit)++    let day = digits `base` 10++    if 1 <= day && day <= 31+        then return day+        else fail "Invalid day"++{-| Parse a 2-digit hour++    This corresponds to the @time-hour@ rule from the official grammar+-}+timeHour :: Parser Int+timeHour = do+    digits <- Monad.replicateM 2 (Text.Parser.Char.satisfy digit)++    let hour = digits `base` 10++    if 0 <= hour && hour < 24+        then return hour+        else fail "Invalid hour"++{-| Parse a 2-digit minute++    This corresponds to the @time-minute@ rule from the official grammar+-}+timeMinute :: Parser Int+timeMinute = do+    digits <- Monad.replicateM 2 (Text.Parser.Char.satisfy digit)++    let minute = digits `base` 10++    if 0 <= minute && minute < 60+        then return minute+        else fail "Invalid minute"++{-| Parse a 2-digit second++    This corresponds to the @time-second@ rule from the official grammar+-}+timeSecond :: Parser Pico+timeSecond = do+    digits <- Monad.replicateM 2 (Text.Parser.Char.satisfy digit)++    let second = digits `base` 10++    if 0 <= second && second < 60+        then return second+        else fail "Invalid second"++{-| Parse the fractional component of a second++    This corresponds to the @time-secfrac@ rule from the official grammar+-}+timeSecFrac :: Parser (Pico, Word)+timeSecFrac = do+    _ <- Text.Parser.Char.text "."++    digits <- some (Text.Parser.Char.satisfy digit)++    let precision = fromIntegral (length digits)++    return (fromRational ((digits `base` 10) % (10 ^ precision)), precision)++{-| Parse an identifier (i.e. a variable or built-in)++    Variables can have an optional index to disambiguate shadowed variables++    This corresponds to the @identifier@ rule from the official grammar+-}+identifier :: Parser Var+identifier = do+    x <- label++    let indexed = try $ do+            whitespace+            _at+            whitespace+            n <- naturalLiteral+            return (fromIntegral n)++    n <- indexed <|> pure 0+    return (V x n)++whitespaceChunk :: Parser ()+whitespaceChunk =+    choice+        [ void (Dhall.Parser.Combinators.takeWhile1 predicate)+        , void (Text.Parser.Char.text "\r\n" <?> "newline")+        , void lineComment+        , void blockComment+        ] <?> "whitespace"+  where+    predicate c = c == ' ' || c == '\t' || c == '\n'++-- | Parse a hexademical number and convert to the corresponding `Int`+hexNumber :: Parser Int+hexNumber = choice [ hexDigit, hexUpper, hexLower ]+  where+    hexDigit = do+        c <- Text.Parser.Char.satisfy predicate+        return (Char.ord c - Char.ord '0')+      where+        predicate c = '0' <= c && c <= '9'++    hexUpper = do+        c <- Text.Parser.Char.satisfy predicate+        return (10 + Char.ord c - Char.ord 'A')+      where+        predicate c = 'A' <= c && c <= 'F'++    hexLower = do+        c <- Text.Parser.Char.satisfy predicate+        return (10 + Char.ord c - Char.ord 'a')+      where+        predicate c = 'a' <= c && c <= 'f'++-- | Same as `lineComment` except that this doesn't parse the end-of-line+--   character+lineCommentPrefix :: Parser Text+lineCommentPrefix = do+    _ <- text "--"++    let predicate c = ('\x20' <= c && c <= '\x10FFFF') || c == '\t'++    commentText <- Dhall.Parser.Combinators.takeWhile predicate++    return ("--" <> commentText)++-- | Parse a Dhall's single-line comment, starting from `--` and until the+--   last character of the line /before/ the end-of-line character+lineComment :: Parser Text+lineComment = try (lineCommentPrefix <* endOfLine)++-- | Parsed text doesn't include opening braces+blockComment :: Parser Text+blockComment = do+    _ <- text "{-"+    c <- blockCommentContinue+    pure ("{-" <> c <> "-}")++blockCommentChunk :: Parser Text+blockCommentChunk =+    choice+        [ blockComment  -- Nested block comment+        , characters+        , character+        , endOfLine+        ]+  where+    characters = (Dhall.Parser.Combinators.takeWhile1 predicate)+      where+        predicate c =+                '\x20' <= c && c <= '\x10FFFF' && c /= '-' && c /= '{'+            ||  c == '\n'+            ||  c == '\t'++    character = (Dhall.Parser.Combinators.satisfy predicate)+      where+        predicate c = '\x20' <= c && c <= '\x10FFFF' || c == '\n' || c == '\t'++blockCommentContinue :: Parser Text+blockCommentContinue = endOfComment <|> continue+  where+    endOfComment = void (text "-}") *> pure ""++    continue = do+        c <- blockCommentChunk+        c' <- blockCommentContinue+        pure (c <> c')++simpleLabel :: Bool -> Parser Text+simpleLabel allowReserved = try $ do+    c    <- Text.Parser.Char.satisfy headCharacter+    rest <- Dhall.Parser.Combinators.takeWhile tailCharacter+    let t = Data.Text.cons c rest+    let isNotAKeyword = not $ t `Data.HashSet.member` reservedKeywords+    let isNotAReservedIdentifier = not $ t `Data.HashSet.member` reservedIdentifiers+    Monad.guard (isNotAKeyword && (allowReserved || isNotAReservedIdentifier))+    return t++headCharacter :: Char -> Bool+headCharacter c = alpha c || c == '_'++tailCharacter :: Char -> Bool+tailCharacter c = alphaNum c || c == '_' || c == '-' || c == '/'++backtickLabel :: Parser Text+backtickLabel = do+    _ <- char '`'+    t <- Dhall.Parser.Combinators.takeWhile predicate+    _ <- char '`'+    return t+  where+    predicate c =+            '\x20' <= c && c <= '\x5F'+        ||  '\x61' <= c && c <= '\x7E'++{-| Parse a braced sequence of comma-separated labels++    For example, this is used to parse the record projection syntax++    This corresponds to the @labels@ rule in the official grammar+-}+labels :: Parser [Text]+labels = do+    _openBrace++    whitespace++    nonEmptyLabels <|> emptyLabels+  where+    emptyLabels = do+        try (optional (_comma *> whitespace) *> _closeBrace)++        pure []++    nonEmptyLabels = do+        x  <- try (optional (_comma *> whitespace) *> anyLabelOrSome)++        whitespace++        xs <- many (try (_comma *> whitespace *> anyLabelOrSome) <* whitespace)++        _ <- optional (_comma *> whitespace)++        _closeBrace++        return (x : xs)++{-| Parse a label (e.g. a variable\/field\/alternative name)++    Rejects labels that match built-in names (e.g. @Natural/even@)++    This corresponds to the @nonreserved-label@ rule in the official grammar+-}+label :: Parser Text+label = backtickLabel <|> simpleLabel False <?> "label"++{-| Same as `label` except that built-in names are allowed++    This corresponds to the @any-label@ rule in the official grammar+-}+anyLabel :: Parser Text+anyLabel = (do+    t <- backtickLabel <|> simpleLabel True+    return t ) <?> "any label"++{-| Same as `anyLabel` except that `Some` is allowed++    This corresponds to the @any-label-or-some@ rule in the official grammar+-}++anyLabelOrSome :: Parser Text+anyLabelOrSome = try anyLabel <|> ("Some" <$ _Some)++{-| Parse a valid Bash environment variable name++    This corresponds to the @bash-environment-variable@ rule in the official+    grammar+-}+bashEnvironmentVariable :: Parser Text+bashEnvironmentVariable = satisfy predicate0 <> star (satisfy predicate1)+  where+    predicate0 c = alpha c || c == '_'++    predicate1 c = alphaNum c || c == '_'++{-| Parse a valid POSIX environment variable name, which permits a wider range+    of characters than a Bash environment variable name++    This corresponds to the @posix-environment-variable@ rule in the official+    grammar+-}+posixEnvironmentVariable :: Parser Text+posixEnvironmentVariable = plus posixEnvironmentVariableCharacter++posixEnvironmentVariableCharacter :: Parser Text+posixEnvironmentVariableCharacter =+    escapeCharacter <|> satisfy predicate1+  where+    escapeCharacter = do+        _ <- char '\\'++        c <- Text.Parser.Char.satisfy (`elem` ("\"\\abfnrtv" :: String))++        case c of+            '"'  -> return "\""+            '\\' -> return "\\"+            'a'  -> return "\a"+            'b'  -> return "\b"+            'f'  -> return "\f"+            'n'  -> return "\n"+            'r'  -> return "\r"+            't'  -> return "\t"+            'v'  -> return "\v"+            _    -> empty++    predicate1 c =+            ('\x20' <= c && c <= '\x21')+        ||  ('\x23' <= c && c <= '\x3C')+        ||  ('\x3E' <= c && c <= '\x5B')+        ||  ('\x5D' <= c && c <= '\x7E')++quotedPathCharacter :: Char -> Bool+quotedPathCharacter c =+        ('\x20' <= c && c <= '\x21')+    ||  ('\x23' <= c && c <= '\x2E')+    ||  ('\x30' <= c && c <= '\x10FFFF')++{-| The @pathComponent@ function uses this type to distinguish whether to parse+    a URL path component or a file path component+-}+data ComponentType = URLComponent | FileComponent++-- | Parse a path component+pathComponent :: ComponentType -> Parser Text+pathComponent componentType = do+    _ <- "/" :: Parser Text++    let pathData =+            case componentType of+                FileComponent ->+                    Text.Megaparsec.takeWhile1P Nothing Dhall.Syntax.pathCharacter+                URLComponent ->+                    star pchar++    let quotedPathData = do+            _ <- char '"'+            t <- Text.Megaparsec.takeWhile1P Nothing quotedPathCharacter+            _ <- char '"'+            return t++    case componentType of+        FileComponent -> quotedPathData <|> pathData+        URLComponent -> pathData++-- | Parse a `File`+file_ :: ComponentType -> Parser File+file_ componentType = do+    let emptyPath =+            case componentType of+                URLComponent  -> pure (pure "")+                FileComponent -> empty++    path <- Data.List.NonEmpty.some1 (pathComponent componentType) <|> emptyPath++    let directory = Directory (reverse (Data.List.NonEmpty.init path))+    let file      = Data.List.NonEmpty.last path++    return (File {..})++scheme_ :: Parser Scheme+scheme_ =+        ("http" :: Parser Text)+    *>  ((("s" :: Parser Text) *> pure HTTPS) <|> pure HTTP)+    <*  ("://" :: Parser Text)++{-| Parse an HTTP(S) URL without trailing whitespace++    This corresponds to the @http-raw@ rule in the official grammar+-}+httpRaw :: Parser URL+httpRaw = do+    scheme    <- scheme_+    authority <- authority_+    path      <- file_ URLComponent+    query     <- optional (("?" :: Parser Text) *> query_)++    let headers = Nothing++    return (URL {..})++authority_ :: Parser Text+authority_ = option (try (userinfo <> "@")) <> host <> option (":" <> port)++userinfo :: Parser Text+userinfo = star (satisfy predicate <|> pctEncoded)+  where+    predicate c = unreserved c || subDelims c || c == ':'++host :: Parser Text+host = choice [ ipLiteral, try ipV4Address, domain ]++port :: Parser Text+port = star (satisfy digit)++ipLiteral :: Parser Text+ipLiteral = "[" <> (ipV6Address <|> ipVFuture) <> "]"++ipVFuture :: Parser Text+ipVFuture = "v" <> plus (satisfy hexdig) <> "." <> plus (satisfy predicate)+  where+    predicate c = unreserved c || subDelims c || c == ':'++ipV6Address :: Parser Text+ipV6Address =+    choice+        [ try alternative0+        , try alternative1+        , try alternative2+        , try alternative3+        , try alternative4+        , try alternative5+        , try alternative6+        , try alternative7+        ,     alternative8+        ]+  where+    alternative0 = count 6 (h16 <> ":") <> ls32++    alternative1 = "::" <> count 5 (h16 <> ":") <> ls32++    alternative2 = option h16 <> "::" <> count 4 (h16 <> ":") <> ls32++    alternative3 =+            option (h16 <> range 0 1 (try (":" <> h16)))+        <>  "::"+        <>  count 3 (h16 <> ":")+        <>  ls32++    alternative4 =+            option (h16 <> range 0 2 (try (":" <> h16)))+        <>  "::"+        <>  count 2 (h16 <> ":")+        <>  ls32++    alternative5 =+            option (h16 <> range 0 3 (try (":" <> h16)))+        <>  "::"+        <>  h16+        <>  ":"+        <>  ls32++    alternative6 =+        option (h16 <> range 0 4 (try (":" <> h16))) <> "::" <> ls32++    alternative7 =+        option (h16 <> range 0 5 (try (":" <> h16))) <> "::" <> h16++    alternative8 =+        option (h16 <> range 0 6 (try (":" <> h16))) <> "::"++h16 :: Parser Text+h16 = range 1 3 (satisfy hexdig)++ls32 :: Parser Text+ls32 = try (h16 <> ":" <> h16) <|> ipV4Address++ipV4Address :: Parser Text+ipV4Address = decOctet <> "." <> decOctet <> "." <> decOctet <> "." <> decOctet++decOctet :: Parser Text+decOctet =+    choice+        [ try alternative4+        , try alternative3+        , try alternative2+        , try alternative1+        ,     alternative0+        ]+  where+    alternative0 = satisfy digit++    alternative1 = satisfy predicate <> satisfy digit+      where+        predicate c = '\x31' <= c && c <= '\x39'++    alternative2 = "1" <> count 2 (satisfy digit)++    alternative3 = "2" <> satisfy predicate <> satisfy digit+      where+        predicate c = '\x30' <= c && c <= '\x34'++    alternative4 = "25" <> satisfy predicate+      where+        predicate c = '\x30' <= c && c <= '\x35'++domain :: Parser Text+domain = domainLabel <> star ("." <> domainLabel ) <> option "."++domainLabel :: Parser Text+domainLabel = plus alphaNum_ <> star (plus "-" <> plus alphaNum_)+  where+    alphaNum_ = satisfy alphaNum++pchar :: Parser Text+pchar = satisfy predicate <|> pctEncoded+  where+    predicate c = unreserved c || subDelims c || c == ':' || c == '@'++query_ :: Parser Text+query_ = star (pchar <|> satisfy predicate)+  where+    predicate c = c == '/' || c == '?'++pctEncoded :: Parser Text+pctEncoded = "%" <> count 2 (satisfy hexdig)++subDelims :: Char -> Bool+subDelims c = c `elem` ("!$&'*+;=" :: String)++unreserved :: Char -> Bool+unreserved c =+    alphaNum c || c == '-' || c == '.' || c == '_' || c == '~'++{-| A variation on `Text.Parser.Char.text` that doesn't quote the expected+    in error messages+-}+text :: Data.Text.Text -> Parser Text+text t = Text.Parser.Char.text t <?> Data.Text.unpack t+{-# INLINE text #-}++{-| A variation on `Text.Parser.Char.char` that doesn't quote the expected+    token in error messages+-}+char :: Char -> Parser Char+char c = Text.Parser.Char.char c <?> [ c ]+{-# INLINE char #-}++reserved :: Data.Text.Text -> Parser ()+reserved x = void (text x)++reservedChar :: Char -> Parser ()+reservedChar c = void (char c)++builtin :: Data.Text.Text -> Parser ()+builtin x = reserved x <?> "built-in"+{-# INLINE builtin #-}++operator :: Data.Text.Text -> Parser ()+operator x = reserved x <?> "operator"+{-# INLINE operator #-}++operatorChar :: Char -> Parser ()+operatorChar x = reservedChar x <?> "operator"+{-# INLINE operatorChar #-}++keyword :: Data.Text.Text -> Parser ()+keyword x = try (void (text x)) <?> "keyword"++{-| Parse the @if@ keyword++    This corresponds to the @if@ rule from the official grammar+-}+_if :: Parser ()+_if = keyword "if"++{-| Parse the @then@ keyword++    This corresponds to the @then@ rule from the official grammar+-}+_then :: Parser ()+_then = keyword "then"++{-| Parse the @else@ keyword++    This corresponds to the @else@ rule from the official grammar+-}+_else :: Parser ()+_else = keyword "else"++{-| Parse the @let@ keyword++    This corresponds to the @let@ rule from the official grammar+-}+_let :: Parser ()+_let = keyword "let"++{-| Parse the @in@ keyword++    This corresponds to the @in@ rule from the official grammar+-}+_in :: Parser ()+_in = keyword "in"++{-| Parse the @as@ keyword++    This corresponds to the @as@ rule from the official grammar+-}+_as :: Parser ()+_as = keyword "as"++{-| Parse the @using@ keyword++    This corresponds to the @using@ rule from the official grammar+-}+_using :: Parser ()+_using = keyword "using"++{-| Parse the @merge@ keyword++    This corresponds to the @merge@ rule from the official grammar+-}+_merge :: Parser ()+_merge = keyword "merge"++{-| Parse the @toMap@ keyword++    This corresponds to the @toMap@ rule from the official grammar+-}+_toMap :: Parser ()+_toMap = keyword "toMap"++{-| Parse the @showConstructor@ keyword++    This corresponds to the @showConstructor@ rule from the official grammar+-}+_showConstructor :: Parser ()+_showConstructor = keyword "showConstructor"++{-| Parse the @assert@ keyword++    This corresponds to the @assert@ rule from the official grammar+-}+_assert :: Parser ()+_assert = keyword "assert"++-- | Parse the @with@ keyword+_with :: Parser ()+_with = keyword "with"++{-| Parse the @Some@ built-in++    This corresponds to the @Some@ rule from the official grammar+-}+_Some :: Parser ()+_Some = keyword "Some"++{-| Parse the @None@ built-in++    This corresponds to the @None@ rule from the official grammar+-}+_None :: Parser ()+_None = builtin "None"++{-| Parse the @Natural/fold@ built-in++    This corresponds to the @Natural-fold@ rule from the official grammar+-}+_NaturalFold :: Parser ()+_NaturalFold = builtin "Natural/fold"++{-| Parse the @Natural/build@ built-in++    This corresponds to the @Natural-build@ rule from the official grammar+-}+_NaturalBuild :: Parser ()+_NaturalBuild = builtin "Natural/build"++{-| Parse the @Natural/isZero@ built-in++    This corresponds to the @Natural-isZero@ rule from the official grammar+-}+_NaturalIsZero :: Parser ()+_NaturalIsZero = builtin "Natural/isZero"++{-| Parse the @Natural/even@ built-in++    This corresponds to the @Natural-even@ rule from the official grammar+-}+_NaturalEven :: Parser ()+_NaturalEven = builtin "Natural/even"++{-| Parse the @Natural/odd@ built-in++    This corresponds to the @Natural-odd@ rule from the official grammar+-}+_NaturalOdd :: Parser ()+_NaturalOdd = builtin "Natural/odd"++{-| Parse the @Natural/toInteger@ built-in++    This corresponds to the @Natural-toInteger@ rule from the official grammar+-}+_NaturalToInteger :: Parser ()+_NaturalToInteger = builtin "Natural/toInteger"++{-| Parse the @Natural/show@ built-in++    This corresponds to the @Natural-show@ rule from the official grammar+-}+_NaturalShow :: Parser ()+_NaturalShow = builtin "Natural/show"++{-| Parse the @Natural/subtract@ built-in++    This corresponds to the @Natural-subtract@ rule from the official grammar+-}+_NaturalSubtract :: Parser ()+_NaturalSubtract = builtin "Natural/subtract"++{-| Parse the @Integer/clamp@ built-in++    This corresponds to the @Integer-clamp@ rule from the official grammar+-}+_IntegerClamp :: Parser ()+_IntegerClamp = builtin "Integer/clamp"++{-| Parse the @Integer/negate@ built-in++    This corresponds to the @Integer-negate@ rule from the official grammar+-}+_IntegerNegate :: Parser ()+_IntegerNegate = builtin "Integer/negate"++{-| Parse the @Integer/show@ built-in++    This corresponds to the @Integer-show@ rule from the official grammar+-}+_IntegerShow :: Parser ()+_IntegerShow = builtin "Integer/show"++{-| Parse the @Integer/toDouble@ built-in++    This corresponds to the @Integer-toDouble@ rule from the official grammar+-}+_IntegerToDouble :: Parser ()+_IntegerToDouble = builtin "Integer/toDouble"++{-| Parse the @Double/show@ built-in++    This corresponds to the @Double-show@ rule from the official grammar+-}+_DoubleShow :: Parser ()+_DoubleShow = builtin "Double/show"++{-| Parse the @List/build@ built-in++    This corresponds to the @List-build@ rule from the official grammar+-}+_ListBuild :: Parser ()+_ListBuild = builtin "List/build"++{-| Parse the @List/fold@ built-in++    This corresponds to the @List-fold@ rule from the official grammar+-}+_ListFold :: Parser ()+_ListFold = builtin "List/fold"++{-| Parse the @List/length@ built-in++    This corresponds to the @List-length@ rule from the official grammar+-}+_ListLength :: Parser ()+_ListLength = builtin "List/length"++{-| Parse the @List/head@ built-in++    This corresponds to the @List-head@ rule from the official grammar+-}+_ListHead :: Parser ()+_ListHead = builtin "List/head"++{-| Parse the @List/last@ built-in++    This corresponds to the @List-last@ rule from the official grammar+-}+_ListLast :: Parser ()+_ListLast = builtin "List/last"++{-| Parse the @List/indexed@ built-in++    This corresponds to the @List-indexed@ rule from the official grammar+-}+_ListIndexed :: Parser ()+_ListIndexed = builtin "List/indexed"++{-| Parse the @List/reverse@ built-in++    This corresponds to the @List-reverse@ rule from the official grammar+-}+_ListReverse :: Parser ()+_ListReverse = builtin "List/reverse"++{-| Parse the @Bool@ built-in++    This corresponds to the @Bool@ rule from the official grammar+-}+_Bool :: Parser ()+_Bool = builtin "Bool"++{-| Parse the @Bytes@ built-in++    This corresponds to the @Bytes@ rule from the official grammar+-}+_Bytes :: Parser ()+_Bytes = builtin "Bytes"++{-| Parse the @Optional@ built-in++    This corresponds to the @Optional@ rule from the official grammar+-}+_Optional :: Parser ()+_Optional = builtin "Optional"++{-| Parse the @Natural@ built-in++    This corresponds to the @Natural@ rule from the official grammar+-}+_Natural :: Parser ()+_Natural = builtin "Natural"++{-| Parse the @Integer@ built-in++    This corresponds to the @Integer@ rule from the official grammar+-}+_Integer :: Parser ()+_Integer = builtin "Integer"++{-| Parse the @Double@ built-in++    This corresponds to the @Double@ rule from the official grammar+-}+_Double :: Parser ()+_Double = builtin "Double"++{-| Parse the @Text@ built-in++    This corresponds to the @Text@ rule from the official grammar+-}+_Text :: Parser ()+_Text = builtin "Text"++{-| Parse the @Text/replace@ built-in++    This corresponds to the @Text-replace@ rule from the official grammar+-}+_TextReplace :: Parser ()+_TextReplace = builtin "Text/replace"++{-| Parse the @Text/show@ built-in++    This corresponds to the @Text-show@ rule from the official grammar+-}+_TextShow :: Parser ()+_TextShow = builtin "Text/show"++{-| Parse the @Date@ bult-in++    This corresponds to the @Date@ rule from the official grammar+-}+_Date :: Parser ()+_Date = builtin "Date"++{-| Parse the @Date/show@ built-in++    This corresponds to the @Date-show@ rule from the official grammar+-}+_DateShow :: Parser ()+_DateShow = builtin "Date/show"++{-| Parse the @Time@ bult-in++    This corresponds to the @Time@ rule from the official grammar+-}+_Time :: Parser ()+_Time = builtin "Time"++{-| Parse the @Time/show@ built-in++    This corresponds to the @Time-show@ rule from the official grammar+-}+_TimeShow :: Parser ()+_TimeShow = builtin "Time/show"++{-| Parse the @TimeZone@ bult-in++    This corresponds to the @TimeZone@ rule from the official grammar+-}+_TimeZone :: Parser ()+_TimeZone = builtin "TimeZone"++{-| Parse the @TimeZone/show@ built-in++    This corresponds to the @TimeZone-show@ rule from the official grammar+-}+_TimeZoneShow :: Parser ()+_TimeZoneShow = builtin "TimeZone/show"++{-| Parse the @List@ built-in++    This corresponds to the @List@ rule from the official grammar+-}+_List :: Parser ()+_List = builtin "List"++{-| Parse the @True@ built-in++    This corresponds to the @True@ rule from the official grammar+-}+_True :: Parser ()+_True = builtin "True"++{-| Parse the @False@ built-in++    This corresponds to the @False@ rule from the official grammar+-}+_False :: Parser ()+_False = builtin "False"++{-| Parse a @NaN@ literal++    This corresponds to the @NaN@ rule from the official grammar+-}+_NaN :: Parser ()+_NaN = builtin "NaN"++{-| Parse the @Type@ built-in++    This corresponds to the @Type@ rule from the official grammar+-}+_Type :: Parser ()+_Type = builtin "Type"++{-| Parse the @Kind@ built-in++    This corresponds to the @Kind@ rule from the official grammar+-}+_Kind :: Parser ()+_Kind = builtin "Kind"++{-| Parse the @Sort@ built-in++    This corresponds to the @Sort@ rule from the official grammar+-}+_Sort :: Parser ()+_Sort = builtin "Sort"++{-| Parse the @Location@ keyword++    This corresponds to the @Location@ rule from the official grammar+-}+_Location :: Parser ()+_Location = builtin "Location"++-- | Parse the @=@ symbol+_equal :: Parser ()+_equal = reservedChar '='++-- | Parse the @||@ symbol+_or :: Parser ()+_or = operator "||"++-- | Parse the @+@ symbol+_plus :: Parser ()+_plus = operatorChar '+'++-- | Parse the @++@ symbol+_textAppend :: Parser ()+_textAppend = operator "++"++-- | Parse the @#@ symbol+_listAppend :: Parser ()+_listAppend = operatorChar '#'++-- | Parse the @&&@ symbol+_and :: Parser ()+_and = operator "&&"++-- | Parse the @*@ symbol+_times :: Parser ()+_times = operatorChar '*'++-- | Parse the @==@ symbol+_doubleEqual :: Parser ()+_doubleEqual = operator "=="++-- | Parse the @!=@ symbol+_notEqual :: Parser ()+_notEqual = operator "!="++-- | Parse the @.@ symbol+_dot :: Parser ()+_dot = operatorChar '.'++-- | Parse the @{@ symbol+_openBrace :: Parser ()+_openBrace = reservedChar '{'++-- | Parse the @}@ symbol+_closeBrace :: Parser ()+_closeBrace = reservedChar '}'++-- | Parse the @[@] symbol+_openBracket :: Parser ()+_openBracket = reservedChar '['++-- | Parse the @]@ symbol+_closeBracket :: Parser ()+_closeBracket = reservedChar ']'++-- | Parse the @<@ symbol+_openAngle :: Parser ()+_openAngle = reservedChar '<'++-- | Parse the @>@ symbol+_closeAngle :: Parser ()+_closeAngle = reservedChar '>'++-- | Parse the @|@ symbol+_bar :: Parser ()+_bar = reservedChar '|'++-- | Parse the @,@ symbol+_comma :: Parser ()+_comma = reservedChar ',' <?> "\',\'"++-- | Parse the @(@ symbol+_openParens :: Parser ()+_openParens = reservedChar '('++-- | Parse the @)@ symbol+_closeParens :: Parser ()+_closeParens = reservedChar ')'++-- | Parse the @:@ symbol+_colon :: Parser ()+_colon = reservedChar ':'++-- | Parse the @\@@ symbol+_at :: Parser ()+_at = reservedChar '@' <?> "\"@\""++-- | Parse the equivalence symbol (@===@ or @≡@)+_equivalent :: Parser CharacterSet+_equivalent =+        (Unicode <$ char '≡' <?> "\"≡\"")+    <|> (ASCII <$ text "===" <?> "===")++-- | Parse the @missing@ keyword+_missing :: Parser ()+_missing =+        keyword "missing"+    *>  Text.Megaparsec.notFollowedBy (Text.Parser.Char.satisfy tailCharacter)++-- | Parse the @?@ symbol+_importAlt :: Parser ()+_importAlt = operatorChar '?'++-- | Parse the record combine operator (@/\\@ or @∧@)+_combine :: Parser CharacterSet+_combine =+        (Unicode <$ char '∧' <?> "\"∧\"")+    <|> (ASCII <$ text "/\\" <?> "/\\")++-- | Parse the record type combine operator (@//\\\\@ or @⩓@)+_combineTypes :: Parser CharacterSet+_combineTypes =+        (Unicode <$ char '⩓' <?> "\"⩓\"")+    <|> (ASCII <$ text "//\\\\" <?> "//\\\\")++-- | Parse the record \"prefer\" operator (@//@ or @⫽@)+_prefer :: Parser CharacterSet+_prefer =+        (Unicode <$ char '⫽' <?> "\"⫽\"")+    <|> (ASCII <$ text "//" <?> "//")++-- | Parse a lambda (@\\@ or @λ@)+_lambda :: Parser CharacterSet+_lambda =+        (Unicode <$ char 'λ' <?> "\"λ\"")+    <|> (ASCII <$ char '\\' <?> "\\")++-- | Parse a forall (@forall@ or @∀@)+_forall :: Parser CharacterSet+_forall =+        (Unicode <$ char '∀' <?> "\"∀\"")+    <|> (ASCII <$ text "forall" <?> "forall")++-- | Parse a right arrow (@->@ or @→@)+_arrow :: Parser CharacterSet+_arrow =+        (Unicode <$ char '→' <?> "\"→\"")+    <|> (ASCII <$ text "->" <?> "->")++-- | Parse a double colon (@::@)+_doubleColon :: Parser ()+_doubleColon = operator "::"
src/Dhall/Pretty.hs view
@@ -8,16 +8,18 @@     , prettyExpr      , CharacterSet(..)+    , defaultCharacterSet+    , detectCharacterSet     , prettyCharacterSet -    , layoutOpts+    , Dhall.Pretty.Internal.layout+    , Dhall.Pretty.Internal.layoutOpts++    , escapeEnvironmentVariable+    , UnescapedLabel(..)+    , escapeLabel++    , temporalToText     ) where  import Dhall.Pretty.Internal-import qualified Data.Text.Prettyprint.Doc as Pretty---- | Default layout options-layoutOpts :: Pretty.LayoutOptions-layoutOpts =-    Pretty.defaultLayoutOptions-        { Pretty.layoutPageWidth = Pretty.AvailablePerLine 80 1.0 }
src/Dhall/Pretty/Internal.hs view
@@ -1,989 +1,1991 @@-{-# LANGUAGE CPP               #-}-{-# LANGUAGE OverloadedStrings #-}-{-# OPTIONS_GHC -Wall #-}--{-| This module provides internal pretty-printing utilities which are used by-    other modules but are not part of the public facing API--}--module Dhall.Pretty.Internal (-      Ann(..)-    , annToAnsiStyle-    , prettyExpr--    , CharacterSet(..)-    , prettyCharacterSet--    , prettyVar-    , pretty-    , escapeText--    , prettyConst-    , prettyLabel-    , prettyAnyLabel-    , prettyLabels-    , prettyNatural-    , prettyNumber-    , prettyDouble-    , prettyToStrictText-    , prettyToString--    , docToStrictText--    , builtin-    , keyword-    , literal-    , operator--    , colon-    , comma-    , dot-    , equals-    , forall-    , label-    , lambda-    , langle-    , lbrace-    , lbracket-    , lparen-    , pipe-    , rangle-    , rarrow-    , rbrace-    , rbracket-    , rparen-    ) where--import Dhall.Core--#if MIN_VERSION_base(4,8,0)-#else-import Control.Applicative (Applicative(..), (<$>))-#endif-import Data.Foldable-import Data.Monoid ((<>))-import Data.Text (Text)-import Data.Text.Prettyprint.Doc (Doc, Pretty, space)-import Dhall.Map (Map)-import Dhall.Set (Set)-import Numeric.Natural (Natural)-import Prelude hiding (succ)-import qualified Data.Text.Prettyprint.Doc.Render.Terminal as Terminal--import qualified Data.Char-import qualified Data.HashSet-import qualified Data.List-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-import qualified Dhall.Set--{-| Annotation type used to tag elements in a pretty-printed document for-    syntax highlighting purposes--}-data Ann-  = Keyword     -- ^ Used for syntactic keywords-  | Syntax      -- ^ Syntax punctuation such as commas, parenthesis, and braces-  | Label       -- ^ Record labels-  | Literal     -- ^ Literals such as integers and strings-  | Builtin     -- ^ Builtin types and values-  | Operator    -- ^ Operators--{-| Convert annotations to their corresponding color for syntax highlighting-    purposes--}-annToAnsiStyle :: Ann -> Terminal.AnsiStyle-annToAnsiStyle Keyword  = Terminal.bold <> Terminal.colorDull Terminal.Green-annToAnsiStyle Syntax   = Terminal.bold <> Terminal.colorDull Terminal.Green-annToAnsiStyle Label    = mempty-annToAnsiStyle Literal  = Terminal.colorDull Terminal.Magenta-annToAnsiStyle Builtin  = Terminal.underlined-annToAnsiStyle Operator = Terminal.bold <> Terminal.colorDull Terminal.Green--data CharacterSet = ASCII | Unicode---- | Pretty print an expression-prettyExpr :: Pretty a => Expr s a -> Doc Ann-prettyExpr = prettyCharacterSet Unicode--{-| Internal utility for pretty-printing, used when generating element lists-    to supply to `enclose` or `enclose'`.  This utility indicates that the-    compact represent is the same as the multi-line representation for each-    element--}-duplicate :: a -> (a, a)-duplicate x = (x, x)---- Annotation helpers-keyword, syntax, label, literal, builtin, operator :: Doc Ann -> Doc Ann-keyword  = Pretty.annotate Keyword-syntax   = Pretty.annotate Syntax-label    = Pretty.annotate Label-literal  = Pretty.annotate Literal-builtin  = Pretty.annotate Builtin-operator = Pretty.annotate Operator--comma, lbracket, rbracket, langle, rangle, lbrace, rbrace, lparen, rparen, pipe, backtick, dollar, colon, equals, dot :: Doc Ann-comma    = syntax Pretty.comma-lbracket = syntax Pretty.lbracket-rbracket = syntax Pretty.rbracket-langle   = syntax Pretty.langle-rangle   = syntax Pretty.rangle-lbrace   = syntax Pretty.lbrace-rbrace   = syntax Pretty.rbrace-lparen   = syntax Pretty.lparen-rparen   = syntax Pretty.rparen-pipe     = syntax Pretty.pipe-backtick = syntax "`"-dollar   = syntax "$"-colon    = syntax ":"-equals   = syntax "="-dot      = syntax "."--lambda :: CharacterSet -> Doc Ann-lambda Unicode = syntax "λ"-lambda ASCII   = syntax "\\"--forall :: CharacterSet -> Doc Ann-forall Unicode = syntax "∀"-forall ASCII   = syntax "forall "--rarrow :: CharacterSet -> Doc Ann-rarrow Unicode = syntax "→"-rarrow ASCII   = syntax "->"---- | Pretty-print a list-list :: [Doc Ann] -> Doc Ann-list   [] = lbracket <> rbracket-list docs =-    enclose-        (lbracket <> space)-        (lbracket <> space)-        (comma <> space)-        (comma <> space)-        (space <> rbracket)-        rbracket-        (fmap duplicate docs)---- | Pretty-print union types and literals-angles :: [(Doc Ann, Doc Ann)] -> Doc Ann-angles   [] = langle <> rangle-angles docs =-    enclose-        (langle <> space)-        (langle <> space)-        (space <> pipe <> space)-        (pipe <> space)-        (space <> rangle)-        rangle-        docs---- | Pretty-print record types and literals-braces :: [(Doc Ann, Doc Ann)] -> Doc Ann-braces   [] = lbrace <> rbrace-braces docs =-    enclose-        (lbrace <> space)-        (lbrace <> space)-        (comma <> space)-        (comma <> space)-        (space <> rbrace)-        rbrace-        docs---- | Pretty-print anonymous functions and function types-arrows :: CharacterSet -> [(Doc Ann, Doc Ann)] -> Doc Ann-arrows ASCII =-    enclose'-        ""-        "    "-        (" " <> rarrow ASCII <> " ")-        (rarrow ASCII <> "  ")-arrows Unicode =-    enclose'-        ""-        "  "-        (" " <> rarrow Unicode <> " ")-        (rarrow Unicode <> " ")--combine :: CharacterSet -> Text-combine ASCII   = "/\\"-combine Unicode = "∧"--combineTypes :: CharacterSet -> Text-combineTypes ASCII   = "//\\\\"-combineTypes Unicode = "⩓"--prefer :: CharacterSet -> Text-prefer ASCII   = "//"-prefer Unicode = "⫽"--{-| Format an expression that holds a variable number of elements, such as a-    list, record, or union--}-enclose-    :: Doc ann-    -- ^ Beginning document for compact representation-    -> Doc ann-    -- ^ Beginning document for multi-line representation-    -> Doc ann-    -- ^ Separator for compact representation-    -> Doc ann-    -- ^ Separator for multi-line representation-    -> Doc ann-    -- ^ Ending document for compact representation-    -> Doc ann-    -- ^ Ending document for multi-line representation-    -> [(Doc ann, Doc ann)]-    -- ^ Elements to format, each of which is a pair: @(compact, multi-line)@-    -> Doc ann-enclose beginShort _         _        _       endShort _       []   =-    beginShort <> endShort-  where-enclose beginShort beginLong sepShort sepLong endShort endLong docs =-    Pretty.group-        (Pretty.flatAlt-            (Pretty.align-                (mconcat (zipWith combineLong (beginLong : repeat sepLong) docsLong) <> endLong)-            )-            (mconcat (zipWith combineShort (beginShort : repeat sepShort) docsShort) <> endShort)-        )-  where-    docsShort = fmap fst docs--    docsLong = fmap snd docs--    combineLong x y = x <> y <> Pretty.hardline--    combineShort x y = x <> y--{-| Format an expression that holds a variable number of elements without a-    trailing document such as nested `let`, nested lambdas, or nested `forall`s--}-enclose'-    :: Doc ann-    -- ^ Beginning document for compact representation-    -> Doc ann-    -- ^ Beginning document for multi-line representation-    -> Doc ann-    -- ^ Separator for compact representation-    -> Doc ann-    -- ^ Separator for multi-line representation-    -> [(Doc ann, Doc ann)]-    -- ^ Elements to format, each of which is a pair: @(compact, multi-line)@-    -> Doc ann-enclose' beginShort beginLong sepShort sepLong docs =-    Pretty.group (Pretty.flatAlt long short)-  where-    longLines = zipWith (<>) (beginLong : repeat sepLong) docsLong--    long =-        Pretty.align (mconcat (Data.List.intersperse Pretty.hardline longLines))--    short = mconcat (zipWith (<>) (beginShort : repeat sepShort) docsShort)--    docsShort = fmap fst docs--    docsLong = fmap snd docs--alpha :: Char -> Bool-alpha c = ('\x41' <= c && c <= '\x5A') || ('\x61' <= c && c <= '\x7A')--digit :: Char -> Bool-digit c = '\x30' <= c && c <= '\x39'--headCharacter :: Char -> Bool-headCharacter c = alpha c || c == '_'--tailCharacter :: Char -> Bool-tailCharacter c = alpha c || digit c || c == '_' || c == '-' || c == '/'--prettyLabelShared :: Bool -> Text -> Doc Ann-prettyLabelShared allowReserved a = label doc-    where-        doc =-            case Text.uncons a of-                Just (h, t)-                    | headCharacter h && Text.all tailCharacter t && (allowReserved || not (Data.HashSet.member a reservedIdentifiers))-                        -> Pretty.pretty a-                _       -> backtick <> Pretty.pretty a <> backtick--prettyLabel :: Text -> Doc Ann-prettyLabel = prettyLabelShared False--prettyAnyLabel :: Text -> Doc Ann-prettyAnyLabel = prettyLabelShared True--prettyLabels :: Set Text -> Doc Ann-prettyLabels a-    | Data.Set.null (Dhall.Set.toSet a) =-        lbrace <> rbrace-    | otherwise =-        braces (map (duplicate . prettyAnyLabel) (Dhall.Set.toList a))--prettyNumber :: Integer -> Doc Ann-prettyNumber = literal . Pretty.pretty--prettyNatural :: Natural -> Doc Ann-prettyNatural = literal . Pretty.pretty--prettyDouble :: Double -> Doc Ann-prettyDouble = literal . Pretty.pretty--prettyConst :: Const -> Doc Ann-prettyConst Type = builtin "Type"-prettyConst Kind = builtin "Kind"-prettyConst Sort = builtin "Sort"--prettyVar :: Var -> Doc Ann-prettyVar (V x 0) = label (Pretty.unAnnotate (prettyLabel x))-prettyVar (V x n) = label (Pretty.unAnnotate (prettyLabel x <> "@" <> prettyNumber n))--prettyCharacterSet :: Pretty a => CharacterSet -> Expr s a -> Doc Ann-prettyCharacterSet characterSet = prettyExpression-  where-    prettyExpression a0@(Lam _ _ _) =-        arrows characterSet (fmap duplicate (docs a0))-      where-        docs (Lam a b c) = Pretty.group (Pretty.flatAlt long short) : docs c-          where-            long =  (lambda characterSet <> space)-                <>  Pretty.align-                    (   (lparen <> space)-                    <>  prettyLabel a-                    <>  Pretty.hardline-                    <>  (colon <> space)-                    <>  prettyExpression b-                    <>  Pretty.hardline-                    <>  rparen-                    )--            short = (lambda characterSet <> lparen)-                <>  prettyLabel a-                <>  (space <> colon <> space)-                <>  prettyExpression b-                <>  rparen-        docs (Note  _ c) = docs c-        docs          c  = [ prettyExpression c ]-    prettyExpression a0@(BoolIf _ _ _) =-        Pretty.group (Pretty.flatAlt long short)-      where-        prefixesLong =-                "      "-            :   cycle-                    [ Pretty.hardline <> keyword "then" <> "  "-                    , Pretty.hardline <> keyword "else" <> "  "-                    ]--        prefixesShort =-                ""-            :   cycle-                    [ space <> keyword "then" <> space-                    , space <> keyword "else" <> space-                    ]--        longLines = zipWith (<>) prefixesLong (docsLong a0)--        long =-            Pretty.align (mconcat (Data.List.intersperse Pretty.hardline longLines))--        short = mconcat (zipWith (<>) prefixesShort (docsShort a0))--        docsLong (BoolIf a b c) =-            docLong ++ docsLong c-          where-            docLong =-                [   keyword "if" <> " " <> prettyExpression a-                ,   prettyExpression b-                ]-        docsLong (Note  _    c) = docsLong c-        docsLong             c  = [ prettyExpression c ]--        docsShort (BoolIf a b c) =-            docShort ++ docsShort c-          where-            docShort =-                [   keyword "if" <> " " <> prettyExpression a-                ,   prettyExpression b-                ]-        docsShort (Note  _    c) = docsShort c-        docsShort             c  = [ prettyExpression c ]-    prettyExpression (Let as b) =-        enclose' "" "" space Pretty.hardline-            (fmap duplicate (fmap docA (toList as)) ++ [ docB ])-      where-        docA (Binding c Nothing e) =-            Pretty.group (Pretty.flatAlt long short)-          where-            long =  keyword "let" <> space-                <>  Pretty.align-                    (   prettyLabel c-                    <>  space <> equals-                    <>  Pretty.hardline-                    <>  "  "-                    <>  prettyExpression e-                    )--            short = keyword "let" <> space-                <>  prettyLabel c-                <>  (space <> equals <> space)-                <>  prettyExpression e-        docA (Binding c (Just d) e) =-            Pretty.group (Pretty.flatAlt long short)-          where-            long = keyword "let" <> space-                <>  Pretty.align-                    (   prettyLabel c-                    <>  Pretty.hardline-                    <>  colon <> space-                    <>  prettyExpression d-                    <>  Pretty.hardline-                    <>  equals <> space-                    <>  prettyExpression e-                    )--            short = keyword "let" <> space-                <>  prettyLabel c-                <>  space <> colon <> space-                <>  prettyExpression d-                <>  space <> equals <> space-                <>  prettyExpression e--        docB =-            ( keyword "in" <> " " <> prettyExpression b-            , keyword "in" <> "  "  <> prettyExpression b-            )-    prettyExpression a0@(Pi _ _ _) =-        arrows characterSet (fmap duplicate (docs a0))-      where-        docs (Pi "_" b c) = prettyOperatorExpression b : docs c-        docs (Pi a   b c) = Pretty.group (Pretty.flatAlt long short) : docs c-          where-            long =  forall characterSet <> space-                <>  Pretty.align-                    (   lparen <> space-                    <>  prettyLabel a-                    <>  Pretty.hardline-                    <>  colon <> space-                    <>  prettyExpression b-                    <>  Pretty.hardline-                    <>  rparen-                    )--            short = forall characterSet <> lparen-                <>  prettyLabel a-                <>  space <> colon <> space-                <>  prettyExpression b-                <>  rparen-        docs (Note _   c) = docs c-        docs           c  = [ prettyExpression c ]-    prettyExpression (Note _ a) =-        prettyExpression a-    prettyExpression a0 =-        prettyAnnotatedExpression a0--    prettyAnnotatedExpression :: Pretty a => Expr s a -> Doc Ann-    prettyAnnotatedExpression (Merge a b (Just c)) =-        Pretty.group (Pretty.flatAlt long short)-      where-        long =-            Pretty.align-                (   keyword "merge"-                <>  Pretty.hardline-                <>  prettyImportExpression a-                <>  Pretty.hardline-                <>  prettyImportExpression b-                <>  Pretty.hardline-                <>  colon <> space-                <>  prettyApplicationExpression c-                )--        short = keyword "merge" <> space-            <>  prettyImportExpression a-            <>  " "-            <>  prettyImportExpression b-            <>  space <> colon <> space-            <>  prettyApplicationExpression c-    prettyAnnotatedExpression (Merge a b Nothing) =-        Pretty.group (Pretty.flatAlt long short)-      where-        long =-            Pretty.align-                (   keyword "merge"-                <>  Pretty.hardline-                <>  prettyImportExpression a-                <>  Pretty.hardline-                <>  prettyImportExpression b-                )--        short = keyword "merge" <> space-            <>  prettyImportExpression a-            <>  " "-            <>  prettyImportExpression b-    prettyAnnotatedExpression a0@(Annot _ _) =-        enclose'-            ""-            "  "-            (" " <> colon <> " ")-            (colon <> space)-            (fmap duplicate (docs a0))-      where-        docs (Annot a b) = prettyOperatorExpression a : docs b-        docs (Note  _ b) = docs b-        docs          b  = [ prettyExpression b ]-    prettyAnnotatedExpression (ListLit (Just a) b) =-            list (map prettyExpression (Data.Foldable.toList b))-        <>  " : "-        <>  prettyApplicationExpression (App List a)-    prettyAnnotatedExpression (OptionalLit a b) =-            list (map prettyExpression (Data.Foldable.toList b))-        <>  " : "-        <>  prettyApplicationExpression (App Optional a)-    prettyAnnotatedExpression (Note _ a) =-        prettyAnnotatedExpression a-    prettyAnnotatedExpression a0 =-        prettyOperatorExpression a0--    prettyOperatorExpression :: Pretty a => Expr s a -> Doc Ann-    prettyOperatorExpression = prettyImportAltExpression--    prettyOperator :: Text -> [Doc Ann] -> Doc Ann-    prettyOperator op docs =-        enclose'-            ""-            prefix-            (" " <> operator (Pretty.pretty op) <> " ")-            (operator (Pretty.pretty op) <> spacer)-            (reverse (fmap duplicate docs))-      where-        prefix = if Text.length op == 1 then "  " else "    "--        spacer = if Text.length op == 1 then " "  else "  "--    prettyImportAltExpression :: Pretty a => Expr s a -> Doc Ann-    prettyImportAltExpression a0@(ImportAlt _ _) =-        prettyOperator "?" (docs a0)-      where-        docs (ImportAlt a b) = prettyOrExpression b : docs a-        docs (Note      _ b) = docs b-        docs              b  = [ prettyOrExpression b ]-    prettyImportAltExpression (Note _ a) =-        prettyImportAltExpression a-    prettyImportAltExpression a0 =-        prettyOrExpression a0--    prettyOrExpression :: Pretty a => Expr s a -> Doc Ann-    prettyOrExpression a0@(BoolOr _ _) =-        prettyOperator "||" (docs a0)-      where-        docs (BoolOr a b) = prettyPlusExpression b : docs a-        docs (Note   _ b) = docs b-        docs           b  = [ prettyPlusExpression b ]-    prettyOrExpression (Note _ a) =-        prettyOrExpression a-    prettyOrExpression a0 =-        prettyPlusExpression a0--    prettyPlusExpression :: Pretty a => Expr s a -> Doc Ann-    prettyPlusExpression a0@(NaturalPlus _ _) =-        prettyOperator "+" (docs a0)-      where-        docs (NaturalPlus a b) = prettyTextAppendExpression b : docs a-        docs (Note        _ b) = docs b-        docs                b  = [ prettyTextAppendExpression b ]-    prettyPlusExpression (Note _ a) =-        prettyPlusExpression a-    prettyPlusExpression a0 =-        prettyTextAppendExpression a0--    prettyTextAppendExpression :: Pretty a => Expr s a -> Doc Ann-    prettyTextAppendExpression a0@(TextAppend _ _) =-        prettyOperator "++" (docs a0)-      where-        docs (TextAppend a b) = prettyListAppendExpression b : docs a-        docs (Note       _ b) = docs b-        docs               b  = [ prettyListAppendExpression b ]-    prettyTextAppendExpression (Note _ a) =-        prettyTextAppendExpression a-    prettyTextAppendExpression a0 =-        prettyListAppendExpression a0--    prettyListAppendExpression :: Pretty a => Expr s a -> Doc Ann-    prettyListAppendExpression a0@(ListAppend _ _) =-        prettyOperator "#" (docs a0)-      where-        docs (ListAppend a b) = prettyAndExpression b : docs a-        docs (Note       _ b) = docs b-        docs               b  = [ prettyAndExpression b ]-    prettyListAppendExpression (Note _ a) =-        prettyListAppendExpression a-    prettyListAppendExpression a0 =-        prettyAndExpression a0--    prettyAndExpression :: Pretty a => Expr s a -> Doc Ann-    prettyAndExpression a0@(BoolAnd _ _) =-        prettyOperator "&&" (docs a0)-      where-        docs (BoolAnd a b) = prettyCombineExpression b : docs a-        docs (Note    _ b) = docs b-        docs            b  = [ prettyCombineExpression b ]-    prettyAndExpression (Note _ a) =-        prettyAndExpression a-    prettyAndExpression a0 =-       prettyCombineExpression a0--    prettyCombineExpression :: Pretty a => Expr s a -> Doc Ann-    prettyCombineExpression a0@(Combine _ _) =-        prettyOperator (combine characterSet) (docs a0)-      where-        docs (Combine a b) = prettyPreferExpression b : docs a-        docs (Note    _ b) = docs b-        docs            b  = [ prettyPreferExpression b ]-    prettyCombineExpression (Note _ a) =-        prettyCombineExpression a-    prettyCombineExpression a0 =-        prettyPreferExpression a0--    prettyPreferExpression :: Pretty a => Expr s a -> Doc Ann-    prettyPreferExpression a0@(Prefer _ _) =-        prettyOperator (prefer characterSet) (docs a0)-      where-        docs (Prefer a b) = prettyCombineTypesExpression b : docs a-        docs (Note   _ b) = docs b-        docs           b  = [ prettyCombineTypesExpression b ]-    prettyPreferExpression (Note _ a) =-        prettyPreferExpression a-    prettyPreferExpression a0 =-        prettyCombineTypesExpression a0--    prettyCombineTypesExpression :: Pretty a => Expr s a -> Doc Ann-    prettyCombineTypesExpression a0@(CombineTypes _ _) =-        prettyOperator (combineTypes characterSet) (docs a0)-      where-        docs (CombineTypes a b) = prettyTimesExpression b : docs a-        docs (Note         _ b) = docs b-        docs                 b  = [ prettyTimesExpression b ]-    prettyCombineTypesExpression (Note _ a) =-        prettyCombineTypesExpression a-    prettyCombineTypesExpression a0 =-        prettyTimesExpression a0--    prettyTimesExpression :: Pretty a => Expr s a -> Doc Ann-    prettyTimesExpression a0@(NaturalTimes _ _) =-        prettyOperator "*" (docs a0)-      where-        docs (NaturalTimes a b) = prettyEqualExpression b : docs a-        docs (Note         _ b) = docs b-        docs                 b  = [ prettyEqualExpression b ]-    prettyTimesExpression (Note _ a) =-        prettyTimesExpression a-    prettyTimesExpression a0 =-        prettyEqualExpression a0--    prettyEqualExpression :: Pretty a => Expr s a -> Doc Ann-    prettyEqualExpression a0@(BoolEQ _ _) =-        prettyOperator "==" (docs a0)-      where-        docs (BoolEQ a b) = prettyNotEqualExpression b : docs a-        docs (Note   _ b) = docs b-        docs           b  = [ prettyNotEqualExpression b ]-    prettyEqualExpression (Note _ a) =-        prettyEqualExpression a-    prettyEqualExpression a0 =-        prettyNotEqualExpression a0--    prettyNotEqualExpression :: Pretty a => Expr s a -> Doc Ann-    prettyNotEqualExpression a0@(BoolNE _ _) =-        prettyOperator "!=" (docs a0)-      where-        docs (BoolNE a b) = prettyApplicationExpression b : docs a-        docs (Note   _ b) = docs b-        docs           b  = [ prettyApplicationExpression b ]-    prettyNotEqualExpression (Note _ a) =-        prettyNotEqualExpression a-    prettyNotEqualExpression a0 =-        prettyApplicationExpression a0--    prettyApplicationExpression :: Pretty a => Expr s a -> Doc Ann-    prettyApplicationExpression a0 = case a0 of-        App _ _  -> result-        Some _   -> result-        Note _ b -> prettyApplicationExpression b-        _        -> prettyImportExpression a0-      where-        result = enclose' "" "" " " "" (fmap duplicate (reverse (docs a0)))--        docs (App  a b) = prettyImportExpression b : docs a-        docs (Some   a) = [ prettyImportExpression a , builtin "Some"         ]-        docs (Note _ b) = docs b-        docs         b  = [ prettyImportExpression b ]--    prettyImportExpression :: Pretty a => Expr s a -> Doc Ann-    prettyImportExpression (Embed a) =-        Pretty.pretty a-    prettyImportExpression (Note _ a) =-        prettyImportExpression a-    prettyImportExpression a0 =-        prettySelectorExpression a0--    prettySelectorExpression :: Pretty a => Expr s a -> Doc Ann-    prettySelectorExpression (Field a b) =-        prettySelectorExpression a <> dot <> prettyAnyLabel b-    prettySelectorExpression (Project a (Left b)) =-        prettySelectorExpression a <> dot <> prettyLabels b-    prettySelectorExpression (Project a (Right b)) =-            prettySelectorExpression a-        <>  dot-        <>  lparen-        <>  prettyExpression b-        <>  rparen-    prettySelectorExpression (Note _ b) =-        prettySelectorExpression b-    prettySelectorExpression a0 =-        prettyPrimitiveExpression a0--    prettyPrimitiveExpression :: Pretty a => Expr s a -> Doc Ann-    prettyPrimitiveExpression (Var a) =-        prettyVar a-    prettyPrimitiveExpression (Const k) =-        prettyConst k-    prettyPrimitiveExpression Bool =-        builtin "Bool"-    prettyPrimitiveExpression Natural =-        builtin "Natural"-    prettyPrimitiveExpression NaturalFold =-        builtin "Natural/fold"-    prettyPrimitiveExpression NaturalBuild =-        builtin "Natural/build"-    prettyPrimitiveExpression NaturalIsZero =-        builtin "Natural/isZero"-    prettyPrimitiveExpression NaturalEven =-        builtin "Natural/even"-    prettyPrimitiveExpression NaturalOdd =-        builtin "Natural/odd"-    prettyPrimitiveExpression NaturalToInteger =-        builtin "Natural/toInteger"-    prettyPrimitiveExpression NaturalShow =-        builtin "Natural/show"-    prettyPrimitiveExpression Integer =-        builtin "Integer"-    prettyPrimitiveExpression IntegerShow =-        builtin "Integer/show"-    prettyPrimitiveExpression IntegerToDouble =-        builtin "Integer/toDouble"-    prettyPrimitiveExpression Double =-        builtin "Double"-    prettyPrimitiveExpression DoubleShow =-        builtin "Double/show"-    prettyPrimitiveExpression Text =-        builtin "Text"-    prettyPrimitiveExpression TextShow =-        builtin "Text/show"-    prettyPrimitiveExpression List =-        builtin "List"-    prettyPrimitiveExpression ListBuild =-        builtin "List/build"-    prettyPrimitiveExpression ListFold =-        builtin "List/fold"-    prettyPrimitiveExpression ListLength =-        builtin "List/length"-    prettyPrimitiveExpression ListHead =-        builtin "List/head"-    prettyPrimitiveExpression ListLast =-        builtin "List/last"-    prettyPrimitiveExpression ListIndexed =-        builtin "List/indexed"-    prettyPrimitiveExpression ListReverse =-        builtin "List/reverse"-    prettyPrimitiveExpression Optional =-        builtin "Optional"-    prettyPrimitiveExpression None =-        builtin "None"-    prettyPrimitiveExpression OptionalFold =-        builtin "Optional/fold"-    prettyPrimitiveExpression OptionalBuild =-        builtin "Optional/build"-    prettyPrimitiveExpression (BoolLit True) =-        builtin "True"-    prettyPrimitiveExpression (BoolLit False) =-        builtin "False"-    prettyPrimitiveExpression (IntegerLit a)-        | 0 <= a    = literal "+" <> prettyNumber a-        | otherwise = prettyNumber a-    prettyPrimitiveExpression (NaturalLit a) =-        prettyNatural a-    prettyPrimitiveExpression (DoubleLit a) =-        prettyDouble a-    prettyPrimitiveExpression (TextLit a) =-        prettyChunks a-    prettyPrimitiveExpression (Record a) =-        prettyRecord a-    prettyPrimitiveExpression (RecordLit a) =-        prettyRecordLit a-    prettyPrimitiveExpression (Union a) =-        prettyUnion a-    prettyPrimitiveExpression (UnionLit a b c) =-        prettyUnionLit a b c-    prettyPrimitiveExpression (ListLit Nothing b) =-        list (map prettyExpression (Data.Foldable.toList b))-    prettyPrimitiveExpression (Note _ b) =-        prettyPrimitiveExpression b-    prettyPrimitiveExpression a =-        Pretty.group (Pretty.flatAlt long short)-      where-        long =-            Pretty.align-                (lparen <> space <> prettyExpression a <> Pretty.hardline <> rparen)--        short = lparen <> prettyExpression a <> rparen--    prettyKeyValue :: Pretty a => Doc Ann -> (Text, Expr s a) -> (Doc Ann, Doc Ann)-    prettyKeyValue separator (key, val) =-        (       prettyAnyLabel key-            <>  " "-            <>  separator-            <>  " "-            <>  prettyExpression val-        ,       prettyAnyLabel key-            <>  " "-            <>  separator-            <>  long-        )-      where-        long = Pretty.hardline <> "    " <> prettyExpression val--    prettyRecord :: Pretty a => Map Text (Expr s a) -> Doc Ann-    prettyRecord =-        braces . map (prettyKeyValue colon) . Dhall.Map.toList--    prettyRecordLit :: Pretty a => Map Text (Expr s a) -> Doc Ann-    prettyRecordLit a-        | Data.Foldable.null a =-            lbrace <> equals <> rbrace-        | otherwise-            = braces (map (prettyKeyValue equals) (Dhall.Map.toList a))--    prettyAlternative (key, Just val) = prettyKeyValue colon (key, val)-    prettyAlternative (key, Nothing ) = duplicate (prettyAnyLabel key)--    prettyUnion :: Pretty a => Map Text (Maybe (Expr s a)) -> Doc Ann-    prettyUnion =-        angles . map prettyAlternative . Dhall.Map.toList--    prettyUnionLit-        :: Pretty a-        => Text -> Expr s a -> Map Text (Maybe (Expr s a)) -> Doc Ann-    prettyUnionLit a b c =-        angles (front : map prettyAlternative (Dhall.Map.toList c))-      where-        front = prettyKeyValue equals (a, b)--    prettyChunks :: Pretty a => Chunks s a -> Doc Ann-    prettyChunks (Chunks a b) =-        if any (\(builder, _) -> hasNewLine builder) a || hasNewLine b-        then Pretty.flatAlt long short-        else short-      where-        long =-            Pretty.align-            (   literal ("''" <> Pretty.hardline)-            <>  Pretty.align-                (foldMap prettyMultilineChunk a <> prettyMultilineBuilder b)-            <>  literal "''"-            )--        short =-            literal "\"" <> foldMap prettyChunk a <> literal (prettyText b <> "\"")--        hasNewLine = Text.any (== '\n')--        prettyMultilineChunk (c, d) =-                prettyMultilineBuilder c-            <>  dollar-            <>  lbrace-            <>  prettyExpression d-            <>  rbrace--        prettyMultilineBuilder builder = literal (mconcat docs)-          where-            lazyLines = Text.splitOn "\n" (escapeSingleQuotedText builder)--            docs =-                Data.List.intersperse Pretty.hardline (fmap Pretty.pretty lazyLines)--        prettyChunk (c, d) =-                prettyText c-            <>  syntax "${"-            <>  prettyExpression d-            <>  syntax rbrace--        prettyText t = literal (Pretty.pretty (escapeText t))---- | Pretty-print a value-pretty :: Pretty a => a -> Text-pretty = Pretty.renderStrict . Pretty.layoutPretty options . Pretty.pretty-  where-   options = Pretty.LayoutOptions { Pretty.layoutPageWidth = Pretty.Unbounded }---- | Escape a `Text` literal using Dhall's escaping rules for single-quoted---   @Text@-escapeSingleQuotedText :: Text -> Text-escapeSingleQuotedText inputBuilder = outputBuilder-  where-    outputText = substitute "${" "''${" (substitute "''" "'''" inputBuilder)--    outputBuilder = outputText--    substitute before after = Text.intercalate after . Text.splitOn before--{-| Escape a `Text` literal using Dhall's escaping rules--    Note that the result does not include surrounding quotes--}-escapeText :: Text -> Text-escapeText text = Text.concatMap adapt text-  where-    adapt c-        | '\x20' <= c && c <= '\x21'     = Text.singleton c-        -- '\x22' == '"'-        | '\x23' == c                    = Text.singleton c-        -- '\x24' == '$'-        | '\x25' <= c && c <= '\x5B'     = Text.singleton c-        -- '\x5C' == '\\'-        | '\x5D' <= c && c <= '\x10FFFF' = Text.singleton c-        | c == '"'                       = "\\\""-        | c == '$'                       = "\\$"-        | c == '\\'                      = "\\\\"-        | c == '\b'                      = "\\b"-        | c == '\f'                      = "\\f"-        | c == '\n'                      = "\\n"-        | c == '\r'                      = "\\r"-        | c == '\t'                      = "\\t"-        | otherwise                      = "\\u" <> showDigits (Data.Char.ord c)--    showDigits r0 = Text.pack (map showDigit [q1, q2, q3, r3])-      where-        (q1, r1) = r0 `quotRem` 4096-        (q2, r2) = r1 `quotRem`  256-        (q3, r3) = r2 `quotRem`   16--    showDigit n-        | n < 10    = Data.Char.chr (Data.Char.ord '0' + n)-        | otherwise = Data.Char.chr (Data.Char.ord 'A' + n - 10)--prettyToString :: Pretty a => a -> String-prettyToString =-    Pretty.renderString . Pretty.layoutPretty options . Pretty.pretty-  where-   options = Pretty.LayoutOptions { Pretty.layoutPageWidth = Pretty.Unbounded }--docToStrictText :: Doc ann -> Text.Text-docToStrictText = Pretty.renderStrict . Pretty.layoutPretty options-  where-   options = Pretty.LayoutOptions { Pretty.layoutPageWidth = Pretty.Unbounded }--prettyToStrictText :: Pretty a => a -> Text.Text-prettyToStrictText = docToStrictText . Pretty.pretty+{-# LANGUAGE DeriveAnyClass     #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric      #-}+{-# LANGUAGE DeriveLift         #-}+{-# LANGUAGE LambdaCase         #-}+{-# LANGUAGE OverloadedStrings  #-}+{-# LANGUAGE RecordWildCards    #-}+{-# LANGUAGE ViewPatterns       #-}++{-# OPTIONS_GHC -Wall #-}++{-| This module provides internal pretty-printing utilities which are used by+    other modules but are not part of the public facing API+-}++module Dhall.Pretty.Internal (+      Ann(..)+    , annToAnsiStyle+    , prettyExpr+    , prettySrcExpr++    , CharacterSet(..)+    , defaultCharacterSet+    , detectCharacterSet+    , prettyCharacterSet+    , prettyImportExpression++    , prettyVar+    , pretty_+    , escapeText_+    , escapeEnvironmentVariable+    , prettyEnvironmentVariable++    , prettyConst+    , UnescapedLabel(..)+    , escapeLabel+    , prettyLabel+    , prettyAnyLabel+    , prettyLabels+    , prettyNatural+    , prettyNumber+    , prettyInt+    , prettyDouble+    , prettyToStrictText+    , prettyToString+    , prettyBase16+    , layout+    , layoutOpts++    , docToStrictText++    , builtin+    , keyword+    , literal+    , operator++    , colon+    , comma+    , dot+    , equals+    , forall_+    , label+    , lambda+    , langle+    , lbrace+    , lbracket+    , lparen+    , pipe+    , rangle+    , rarrow+    , rbrace+    , rbracket+    , rparen++    , temporalToText+    ) where++import                Control.DeepSeq               (NFData)+import                Data.Aeson+    ( FromJSON (..)+    , Value (String)+    )+import                Data.Aeson.Types              (typeMismatch, unexpected)+import                Data.ByteString               (ByteString)+import                Data.Data                     (Data)+import                Data.Foldable+import                Data.List.NonEmpty            (NonEmpty (..))+import                Data.Text                     (Text)+import                Dhall.Map                     (Map)+import                Dhall.Src                     (Src (..))+import                Dhall.Syntax+import {-# SOURCE #-} Dhall.Syntax.Instances.Pretty ()+import                GHC.Generics                  (Generic)+import                Language.Haskell.TH.Syntax    (Lift)+import                Lens.Micro                    (cosmosOf, foldMapOf)+import                Numeric.Natural               (Natural)+import                Prettyprinter                 (Doc, Pretty, space)++import qualified Control.Exception             as Exception+import qualified Data.ByteString.Base16        as Base16+import qualified Data.Char+import qualified Data.HashSet+import qualified Data.List                     as List+import qualified Data.List.NonEmpty            as NonEmpty+import qualified Data.Maybe+import qualified Data.Text                     as Text+import qualified Data.Text.Encoding            as Encoding+import qualified Data.Time                     as Time+import qualified Dhall.Map                     as Map+import qualified Dhall.Syntax.Operations       as Operations+import qualified Prettyprinter                 as Pretty+import qualified Prettyprinter.Render.String   as Pretty+import qualified Prettyprinter.Render.Terminal as Terminal+import qualified Prettyprinter.Render.Text     as Pretty+import qualified Text.Printf                   as Printf++{-| Annotation type used to tag elements in a pretty-printed document for+    syntax highlighting purposes+-}+data Ann+  = Keyword     -- ^ Used for syntactic keywords+  | Syntax      -- ^ Syntax punctuation such as commas, parenthesis, and braces+  | Label       -- ^ Record labels+  | Literal     -- ^ Literals such as integers and strings+  | Builtin     -- ^ Builtin types and values+  | Operator    -- ^ Operators+  deriving Show++{-| Convert annotations to their corresponding color for syntax highlighting+    purposes+-}+annToAnsiStyle :: Ann -> Terminal.AnsiStyle+annToAnsiStyle Keyword  = Terminal.bold <> Terminal.colorDull Terminal.Green+annToAnsiStyle Syntax   = Terminal.bold <> Terminal.colorDull Terminal.Green+annToAnsiStyle Label    = mempty+annToAnsiStyle Literal  = Terminal.colorDull Terminal.Magenta+annToAnsiStyle Builtin  = Terminal.underlined+annToAnsiStyle Operator = Terminal.bold <> Terminal.colorDull Terminal.Green++-- | This type determines whether to render code as `ASCII` or `Unicode`+data CharacterSet = ASCII | Unicode+    deriving (Eq, Ord, Show, Data, Generic, Lift, NFData)++-- | Since ASCII is a subset of Unicode, if either argument is Unicode, the+-- result is Unicode+instance Semigroup CharacterSet where+    Unicode <> _ = Unicode+    _ <> other = other++instance Monoid CharacterSet where+    mempty = ASCII++instance FromJSON CharacterSet where+  parseJSON (String "unicode") = pure Unicode+  parseJSON (String "ascii") = pure ASCII+  parseJSON v@(String _) = unexpected v+  parseJSON v = typeMismatch "String" v++-- | The character set used by default in functions throughout the Dhall code+-- base.+defaultCharacterSet :: CharacterSet+defaultCharacterSet = Unicode++-- | Detect which character set is used for the syntax of an expression+-- If any parts of the expression uses the Unicode syntax, the whole expression+-- is deemed to be using the Unicode syntax.+detectCharacterSet :: Expr Src a -> CharacterSet+detectCharacterSet = foldMapOf (cosmosOf subExpressions) exprToCharacterSet+  where+    exprToCharacterSet = \case+        Embed _ -> mempty -- Don't go down the embed route, otherwise: <<loop>>+        Lam (Just Unicode) _ _ -> Unicode+        Pi (Just Unicode) _ _ _ -> Unicode+        Combine (Just Unicode) _ _ _ -> Unicode+        CombineTypes (Just Unicode) _ _ -> Unicode+        Prefer (Just Unicode) _ _ _ -> Unicode+        Equivalent (Just Unicode) _ _ -> Unicode+        _ -> mempty++-- | Pretty print an expression+prettyExpr :: Pretty a => Expr s a -> Doc Ann+prettyExpr = prettySrcExpr . denote++prettySrcExpr :: Pretty a => Expr Src a -> Doc Ann+prettySrcExpr = prettyCharacterSet defaultCharacterSet++{-| Internal utility for pretty-printing, used when generating element lists+    to supply to `enclose` or `enclose'`.  This utility indicates that the+    compact represent is the same as the multi-line representation for each+    element+-}+duplicate :: a -> (a, a)+duplicate x = (x, x)++isWhitespace :: Char -> Bool+isWhitespace c =+    case c of+        ' '  -> True+        '\n' -> True+        '\t' -> True+        '\r' -> True+        _    -> False++{-| Used to render inline `Src` spans preserved by the syntax tree++    >>> let unusedSourcePos = Text.Megaparsec.SourcePos "" (Text.Megaparsec.mkPos 1) (Text.Megaparsec.mkPos 1)+    >>> let nonEmptySrc = Src unusedSourcePos unusedSourcePos "-- Documentation for x\n"+    >>> "let" <> " " <> renderSrc id (Just nonEmptySrc) <> "x = 1 in x"+    let -- Documentation for x+        x = 1 in x+    >>> let emptySrc = Src unusedSourcePos unusedSourcePos "      "+    >>> "let" <> " " <> renderSrc id (Just emptySrc) <> "x = 1 in x"+    let x = 1 in x+    >>> "let" <> " " <> renderSrc id Nothing <> "x = 1 in x"+    let x = 1 in x+-}+renderSrc+    :: (Text -> Text)+    -- ^ Used to preprocess the comment string (e.g. to strip whitespace)+    -> Maybe Src+    -- ^ Source span to render (if present)+    -> Doc Ann+renderSrc strip (Just (Src {..}))+    | not (Text.all isWhitespace srcText) =+        renderComment (strip srcText)+renderSrc _ _ =+    mempty++{-| Render a comment.++    Any preprocessing, such as whitespace stripping, needs to be handled by the+    caller, see e.g. 'renderSrc'.++    See the documentation for 'renderSrc' for examples.+-}+renderComment :: Text -> Doc Ann+renderComment text =+    Pretty.align (Pretty.concatWith f newLines <> suffix)+  where+    horizontalSpace c = c == ' ' || c == '\t'++    suffix =+        if Text.null text || Text.last text == '\n'+        then mempty+        else " "++    oldLines = Text.splitOn "\n" text++    spacePrefix = Text.takeWhile horizontalSpace++    commonPrefix a b = case Text.commonPrefixes a b of+        Nothing        -> ""+        Just (c, _, _) -> c++    sharedSpacePrefix []       = ""+    sharedSpacePrefix (l : ls) = foldl' commonPrefix (spacePrefix l) ls++    blank = Text.all horizontalSpace++    newLines =+        case oldLines of+            [] ->+               []+            l0 : ls ->+                let sharedPrefix =+                        sharedSpacePrefix (filter (not . blank) ls)++                    perLine l =+                        case Text.stripPrefix sharedPrefix l of+                            Nothing -> Pretty.pretty l+                            Just l' -> Pretty.pretty l'++                in  Pretty.pretty l0 : map perLine ls++    f x y = x <> Pretty.hardline <> y++{-| This is a variant of 'renderSrc' with the following differences:++      * The 'srcText' is stripped of all whitespace at the start and the end.+      * When the stripped 'srcText' is empty, the result is 'Nothing'.+-}+renderSrcMaybe :: Maybe Src -> Maybe (Doc Ann)+renderSrcMaybe (Just Src{..}) =+    case Text.dropAround isWhitespace srcText of+        "" -> Nothing+        t  -> Just (renderComment t)+renderSrcMaybe _ = Nothing++{-| @+    'containsComment' mSrc ≡ 'Data.Maybe.isJust' ('renderSrcMaybe' mSrc)+    @+-}+containsComment :: Maybe Src -> Bool+containsComment Nothing        = False+containsComment (Just Src{..}) = not (Text.all isWhitespace srcText)++-- Annotation helpers+keyword, syntax, label, literal, builtin, operator :: Doc Ann -> Doc Ann+keyword  = Pretty.annotate Keyword+syntax   = Pretty.annotate Syntax+label    = Pretty.annotate Label+literal  = Pretty.annotate Literal+builtin  = Pretty.annotate Builtin+operator = Pretty.annotate Operator++comma, lbracket, rbracket, langle, rangle, lbrace, rbrace, lparen, rparen, pipe, dollar, colon, equals, dot :: Doc Ann+comma    = syntax Pretty.comma+lbracket = syntax Pretty.lbracket+rbracket = syntax Pretty.rbracket+langle   = syntax Pretty.langle+rangle   = syntax Pretty.rangle+lbrace   = syntax Pretty.lbrace+rbrace   = syntax Pretty.rbrace+lparen   = syntax Pretty.lparen+rparen   = syntax Pretty.rparen+pipe     = syntax Pretty.pipe+dollar   = syntax "$"+colon    = syntax ":"+equals   = syntax "="+dot      = syntax "."++lambda :: CharacterSet -> Doc Ann+lambda Unicode = syntax "λ"+lambda ASCII   = syntax "\\"++forall_ :: CharacterSet -> Doc Ann+forall_ Unicode = syntax "∀"+forall_ ASCII   = syntax "forall "++rarrow :: CharacterSet -> Doc Ann+rarrow Unicode = syntax "→"+rarrow ASCII   = syntax "->"++doubleColon :: Doc Ann+doubleColon = syntax "::"++-- | Pretty-print a list+list :: [Doc Ann] -> Doc Ann+list   [] = lbracket <> rbracket+list docs =+    enclose+        (lbracket <> space)+        (lbracket <> space)+        (comma <> space)+        (comma <> space)+        (space <> rbracket)+        rbracket+        (fmap duplicate docs)++-- | Pretty-print union types and literals+angles :: [(Doc Ann, Doc Ann)] -> Doc Ann+angles   [] = langle <> rangle+angles docs =+    enclose+        (langle <> space)+        (langle <> space)+        (space <> pipe <> space)+        (pipe <> space)+        (space <> rangle)+        rangle+        docs++-- | Pretty-print record types and literals+braces :: [(Doc Ann, Doc Ann)] -> Doc Ann+braces   [] = lbrace <> rbrace+braces docs =+    enclose+        (lbrace <> space)+        (lbrace <> space)+        (comma <> space)+        (comma <> space)+        (space <> rbrace)+        rbrace+        docs++hangingBraces :: Int -> [(Doc Ann, Doc Ann)] -> Doc Ann+hangingBraces _ [] =+    lbrace <> rbrace+hangingBraces n docs =+    Pretty.group+        (Pretty.flatAlt+            (  lbrace+            <> Pretty.hardline+            <> Pretty.indent n+               ( mconcat (map (combineLong separator) docsLong)+               <> rbrace+               )+            )+            (mconcat (zipWith (<>) (beginShort : repeat separator) docsShort) <> space <> rbrace)+        )+  where+    separator = comma <> space++    docsShort = fmap fst docs++    docsLong = fmap snd docs++    beginShort = lbrace <> space++    combineLong x y = x <> y <> Pretty.hardline++unsnoc :: [a] -> Maybe ([a], a)+unsnoc       []   = Nothing+unsnoc (x0 : xs0) = Just (go id x0 xs0)+  where+    go diffXs x      []  = (diffXs [], x)+    go diffXs x (y : ys) = go (diffXs . (x:)) y ys++-- | Pretty-print anonymous functions and function types+arrows :: CharacterSet -> [ Doc Ann ] -> Doc Ann+arrows characterSet docs = Pretty.group (Pretty.flatAlt long short)+  where+    long = Pretty.align (mconcat (List.intersperse Pretty.hardline docs'))+      where+        docs' = case unsnoc docs of+            Nothing -> docs++            Just (init_, last_) -> init' ++ [ last' ]+              where+                 appendArrow doc = doc <> space <> rarrow characterSet++                 init' = map appendArrow init_++                 last' = space <> space <> last_++    short = mconcat (List.intersperse separator docs)+      where+        separator = space <> rarrow characterSet <> space++combine :: CharacterSet -> Text+combine ASCII   = "/\\"+combine Unicode = "∧"++combineTypes :: CharacterSet -> Text+combineTypes ASCII   = "//\\\\"+combineTypes Unicode = "⩓"++prefer :: CharacterSet -> Text+prefer ASCII   = "//"+prefer Unicode = "⫽"++equivalent :: CharacterSet -> Text+equivalent ASCII   = "==="+equivalent Unicode = "≡"++{-| Format an expression that holds a variable number of elements, such as a+    list, record, or union+-}+enclose+    :: Doc ann+    -- ^ Beginning document for compact representation+    -> Doc ann+    -- ^ Beginning document for multi-line representation+    -> Doc ann+    -- ^ Separator for compact representation+    -> Doc ann+    -- ^ Separator for multi-line representation+    -> Doc ann+    -- ^ Ending document for compact representation+    -> Doc ann+    -- ^ Ending document for multi-line representation+    -> [(Doc ann, Doc ann)]+    -- ^ Elements to format, each of which is a pair: @(compact, multi-line)@+    -> Doc ann+enclose beginShort _         _        _       endShort _       []   =+    beginShort <> endShort+enclose beginShort beginLong sepShort sepLong endShort endLong docs =+    Pretty.group+        (Pretty.flatAlt+            (Pretty.align+                (mconcat (zipWith combineLong (beginLong : repeat sepLong) docsLong) <> endLong)+            )+            (mconcat (zipWith combineShort (beginShort : repeat sepShort) docsShort) <> endShort)+        )+  where+    docsShort = fmap fst docs++    docsLong = fmap snd docs++    combineLong x y = x <> y <> Pretty.hardline++    combineShort x y = x <> y++{-| Format an expression that holds a variable number of elements without a+    trailing document such as nested @let@, nested lambdas, or nested @forall@s+-}+enclose'+    :: Doc ann+    -- ^ Beginning document for compact representation+    -> Doc ann+    -- ^ Beginning document for multi-line representation+    -> Doc ann+    -- ^ Separator for compact representation+    -> Doc ann+    -- ^ Separator for multi-line representation+    -> [(Doc ann, Doc ann)]+    -- ^ Elements to format, each of which is a pair: @(compact, multi-line)@+    -> Doc ann+enclose' beginShort beginLong sepShort sepLong docs =+    Pretty.group (Pretty.flatAlt long short)+  where+    longLines = zipWith (<>) (beginLong : repeat sepLong) docsLong++    long =+        Pretty.align (mconcat (List.intersperse Pretty.hardline longLines))++    short = mconcat (zipWith (<>) (beginShort : repeat sepShort) docsShort)++    docsShort = fmap fst docs++    docsLong = fmap snd docs++alpha :: Char -> Bool+alpha c = ('\x41' <= c && c <= '\x5A') || ('\x61' <= c && c <= '\x7A')++digit :: Char -> Bool+digit c = '\x30' <= c && c <= '\x39'++alphaNum :: Char -> Bool+alphaNum c = alpha c || digit c++headCharacter :: Char -> Bool+headCharacter c = alpha c || c == '_'++tailCharacter :: Char -> Bool+tailCharacter c = alphaNum c || c == '_' || c == '-' || c == '/'++-- | The set of labels which do not need to be escaped+data UnescapedLabel+    = NonReservedLabel+    -- ^ This corresponds to the `nonreserved-label` rule in the grammar+    | AnyLabel+    -- ^ This corresponds to the `any-label` rule in the grammar+    | AnyLabelOrSome+    -- ^ This corresponds to the `any-label-or-some` rule in the grammar++-- | Escape a label if it is not valid when unquoted+escapeLabel :: UnescapedLabel -> Text -> Text+escapeLabel allowedLabel l =+    case Text.uncons l of+        Just (h, t)+            | headCharacter h && Text.all tailCharacter t && allowed && l /= "?"+                -> l+        _       -> "`" <> l <> "`"+  where+    allowed = case allowedLabel of+        NonReservedLabel -> notReservedIdentifier+        AnyLabel         -> notReservedKeyword+        AnyLabelOrSome   -> notReservedKeyword || l == "Some"++    notReservedIdentifier = not (Data.HashSet.member l reservedIdentifiers)++    notReservedKeyword = not (Data.HashSet.member l reservedKeywords)++prettyLabelShared :: UnescapedLabel -> Text -> Doc Ann+prettyLabelShared b l = label (Pretty.pretty (escapeLabel b l))++prettyLabel :: Text -> Doc Ann+prettyLabel = prettyLabelShared NonReservedLabel++prettyAnyLabel :: Text -> Doc Ann+prettyAnyLabel = prettyLabelShared AnyLabel++prettyAnyLabelOrSome :: Text -> Doc Ann+prettyAnyLabelOrSome = prettyLabelShared AnyLabelOrSome++prettyKeys+    :: Foldable list+    => (key -> Doc Ann)+    -> list (Maybe Src, key, Maybe Src)+    -> Doc Ann+prettyKeys prettyK keys = Pretty.group (Pretty.flatAlt long short)+  where+    short = (mconcat . Pretty.punctuate dot . map prettyKey . toList) keys++    long =+        case map prettyKey (toList keys) of+            []       -> mempty+            [doc]    -> doc+            doc:docs ->+                  Pretty.align+                . mconcat+                . Pretty.punctuate (Pretty.hardline <> ". ")+                $ Pretty.indent 2 doc : docs++    prettyKey (mSrc0, key, mSrc1) =+          Pretty.align+        . mconcat+        . Pretty.punctuate Pretty.hardline+        . Data.Maybe.catMaybes+        $ [ renderSrcMaybe mSrc0+          , Just (prettyK key)+          , renderSrcMaybe mSrc1+          ]++prettyLabels :: [Text] -> Doc Ann+prettyLabels a+    | null a    = lbrace <> rbrace+    | otherwise = braces (map (duplicate . prettyAnyLabelOrSome) a)++prettyNumber :: Integer -> Doc Ann+prettyNumber = literal . Pretty.pretty++prettyInt :: Int -> Doc Ann+prettyInt = literal . Pretty.pretty++prettyNatural :: Natural -> Doc Ann+prettyNatural = literal . Pretty.pretty++prettyDouble :: Double -> Doc Ann+prettyDouble = literal . Pretty.pretty++prettyConst :: Const -> Doc Ann+prettyConst Type = builtin "Type"+prettyConst Kind = builtin "Kind"+prettyConst Sort = builtin "Sort"++prettyVar :: Var -> Doc Ann+prettyVar (V x 0) = label (Pretty.unAnnotate (prettyLabel x))+prettyVar (V x n) = label (Pretty.unAnnotate (prettyLabel x <> "@" <> prettyInt n))++prettyEnvironmentVariable :: Text -> Doc ann+prettyEnvironmentVariable t = Pretty.pretty (escapeEnvironmentVariable t)++preserveSource :: Expr Src a -> Maybe (Doc Ann)+preserveSource (Note Src{..} (DoubleLit  {})) = Just (Pretty.pretty srcText)+preserveSource (Note Src{..} (IntegerLit {})) = Just (Pretty.pretty srcText)+preserveSource (Note Src{..} (NaturalLit {})) = Just (Pretty.pretty srcText)+preserveSource  _                             = Nothing++-- | Escape an environment variable if not a valid Bash environment variable+escapeEnvironmentVariable :: Text -> Text+escapeEnvironmentVariable t+  | validBashEnvVar t = t+  | otherwise         = "\"" <> escapeText_ t <> "\""+  where+    validBashEnvVar v = case Text.uncons v of+        Nothing      -> False+        Just (c, v') ->+                (alpha c || c == '_')+            &&  Text.all (\c' -> alphaNum c' || c' == '_') v'++{-  There is a close correspondence between the pretty-printers in 'prettyCharacterSet'+    and the sub-parsers in 'Dhall.Parser.Expression.parsers'.  Most pretty-printers are+    named after the corresponding parser and the relationship between pretty-printers+    exactly matches the relationship between parsers.  This leads to the nice emergent+    property of automatically getting all the parentheses and precedences right.++    This approach has one major disadvantage: you can get an infinite loop if+    you add a new constructor to the syntax tree without adding a matching+    case the corresponding builder.+-}++{-| Pretty-print an 'Expr' using the given 'CharacterSet'.++'prettyCharacterSet' largely ignores 'Note's. 'Note's do however matter for+the layout of let-blocks:++>>> let inner = Let (Binding Nothing "x" Nothing Nothing Nothing (NaturalLit 1)) (Var (V "x" 0)) :: Expr Src ()+>>> prettyCharacterSet ASCII (Let (Binding Nothing "y" Nothing Nothing Nothing (NaturalLit 2)) inner)+let y = 2 let x = 1 in x+>>> prettyCharacterSet ASCII (Let (Binding Nothing "y" Nothing Nothing Nothing (NaturalLit 2)) (Note (Src unusedSourcePos unusedSourcePos "") inner))+let y = 2 in let x = 1 in x++This means the structure of parsed let-blocks is preserved.+-}+prettyCharacterSet :: Pretty a => CharacterSet -> Expr Src a -> Doc Ann+prettyCharacterSet characterSet = prettyCompleteExpression+  where+    PrettyPrinters{..} = prettyPrinters characterSet++-- Mainly used by the `Pretty` instance for `Import`+prettyImportExpression :: Pretty a => Expr Src a -> Doc Ann+prettyImportExpression = prettyImportExpression_+  where+    PrettyPrinters{..} = prettyPrinters Unicode++data PrettyPrinters a = PrettyPrinters+    { prettyCompleteExpression :: Expr Src a -> Doc Ann+    , prettyImportExpression_  :: Expr Src a -> Doc Ann+    }++prettyPrinters :: Pretty a => CharacterSet -> PrettyPrinters a+prettyPrinters characterSet =+    PrettyPrinters{..}+  where+    prettyCompleteExpression expression =+        Pretty.group (prettyExpression expression)++    prettyExpression a0@(Lam _ _ _) =+        arrows characterSet (docs a0)+      where+        docs (Lam _ (FunctionBinding { functionBindingVariable = a, functionBindingAnnotation = b }) c) =+            Pretty.group (Pretty.flatAlt long short) : docs c+          where+            long =  (lambda characterSet <> space)+                <>  Pretty.align+                    (   (lparen <> space)+                    <>  prettyLabel a+                    <>  Pretty.hardline+                    <>  (colon <> space)+                    <>  prettyExpression b+                    <>  Pretty.hardline+                    <>  rparen+                    )++            short = (lambda characterSet <> lparen)+                <>  prettyLabel a+                <>  (space <> colon <> space)+                <>  prettyExpression b+                <>  rparen+        docs c+            | Just doc <- preserveSource c =+                [ doc ]+            | Note _ d <- c =+                docs d+            | otherwise =+                [ prettyExpression c ]+    prettyExpression a0@(BoolIf _ _ _) =+        Pretty.group (Pretty.flatAlt long short)+      where+        prefixesLong =+                ""+            :   cycle+                    [ keyword "then" <> "  "+                    , keyword "else" <> "  "+                    ]++        prefixesShort =+                ""+            :   cycle+                    [ space <> keyword "then" <> space+                    , space <> keyword "else" <> space+                    ]++        longLines = zipWith (<>) prefixesLong (docsLong True a0)++        long =+            Pretty.align (mconcat (List.intersperse Pretty.hardline longLines))++        short = mconcat (zipWith (<>) prefixesShort (docsShort a0))++        docsLong initial (BoolIf a b c) =+            docLong ++ docsLong False c+          where+            padding+                | initial   = "   "+                | otherwise = mempty++            docLong =+                [   keyword "if" <> padding <> " " <> prettyExpression a+                ,   prettyExpression b+                ]+        docsLong initial c+            | Just doc <- preserveSource c =+                [ doc ]+            | Note _ d <- c =+                docsLong initial d+            | otherwise =+                [ prettyExpression c ]++        docsShort (BoolIf a b c) =+            docShort ++ docsShort c+          where+            docShort =+                [   keyword "if" <> " " <> prettyExpression a+                ,   prettyExpression b+                ]+        docsShort c+            | Just doc <- preserveSource c =+                [ doc ]+            | Note _ d <- c =+                docsShort d+            | otherwise =+                [ prettyExpression c ]+    prettyExpression (Let a0 b0) =+        enclose' "" "" space Pretty.hardline+            (fmap (duplicate . docA) (toList as) ++ [ docB ])+      where+        MultiLet as b = multiLet a0 b0++        isSpace c = c == ' ' || c == '\t'+        stripSpaces =+            Text.dropAround isSpace+          . Text.intercalate "\n"+          . map (Text.dropWhileEnd isSpace)+          . Text.splitOn "\n"++        -- Strip a single newline character. Needed to ensure idempotency in+        -- cases where we add hard line breaks.+        stripNewline t =+            case Text.uncons t' of+                Just ('\n', t'') -> stripSpaces t''+                _ -> t'+          where t' = stripSpaces t++        docA (Binding src0 c src1 Nothing src2 e) =+            Pretty.group (Pretty.flatAlt long short)+          where+            long =  keyword "let" <> space+                <>  Pretty.align+                    (   renderSrc stripSpaces src0+                    <>  prettyLabel c <> space <> renderSrc stripSpaces src1+                    <>  equals <> Pretty.hardline <> renderSrc stripNewline src2+                    <>  "  " <> prettyExpression e+                    )++            short = keyword "let" <> space <> renderSrc stripSpaces src0+                <>  prettyLabel c <> space <> renderSrc stripSpaces src1+                <>  equals <> space <> renderSrc stripSpaces src2+                <>  prettyExpression e+        docA (Binding src0 c src1 (Just (src3, d)) src2 e) =+                keyword "let" <> space+            <>  Pretty.align+                (   renderSrc stripSpaces src0+                <>  prettyLabel c <> Pretty.hardline <> renderSrc stripNewline src1+                <>  colon <> space <> renderSrc stripSpaces src3 <> prettyExpression d <> Pretty.hardline+                <>  equals <> space <> renderSrc stripSpaces src2+                <>  prettyExpression e+                )++        docB =+            ( keyword "in" <> " " <> prettyExpression b+            , keyword "in" <> "  "  <> prettyExpression b+            )+    prettyExpression a0@(Pi _ _ _ _) =+        arrows characterSet (docs a0)+      where+        docs (Pi _ "_" b c) = prettyOperatorExpression b : docs c+        docs (Pi _ a   b c) = Pretty.group (Pretty.flatAlt long short) : docs c+          where+            long =  forall_ characterSet <> space+                <>  Pretty.align+                    (   lparen <> space+                    <>  prettyLabel a+                    <>  Pretty.hardline+                    <>  colon <> space+                    <>  prettyExpression b+                    <>  Pretty.hardline+                    <>  rparen+                    )++            short = forall_ characterSet <> lparen+                <>  prettyLabel a+                <>  space <> colon <> space+                <>  prettyExpression b+                <>  rparen+        docs c+            | Just doc <- preserveSource c =+                [ doc ]+            | Note _ d <- c =+                docs d+            | otherwise =+                [ prettyExpression c ]+    prettyExpression (With (Dhall.Syntax.shallowDenote -> a) b c) =+            case a of+                With{} ->+                    -- Don't parenthesize an inner with-expression+                    prettyExpression a+                _ ->+                    prettyImportExpression_ a+        <>  Pretty.flatAlt long short+      where+        short = " " <> keyword "with" <> " " <> update++        long =  Pretty.hardline+            <>  "  "+            <>  Pretty.align (keyword "with" <> " " <> update)++        (update, _) =+            prettyKeyValue prettyKey prettyOperatorExpression equals+                (makeKeyValue b c)++        prettyKey (WithLabel text) = prettyAnyLabelOrSome text+        prettyKey  WithQuestion    = syntax "?"+    prettyExpression (Assert a) =+        Pretty.group (Pretty.flatAlt long short)+      where+        short = keyword "assert" <> " " <> colon <> " " <> prettyExpression a++        long =+            Pretty.align+            (  "  " <> keyword "assert"+            <> Pretty.hardline <> colon <> " " <> prettyExpression a+            )+    prettyExpression a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettyExpression b+        | otherwise =+            prettyAnnotatedExpression a++    prettyAnnotatedExpression :: Pretty a => Expr Src a -> Doc Ann+    prettyAnnotatedExpression (Merge a b (Just c)) =+        Pretty.group (Pretty.flatAlt long short)+      where+        long =+            Pretty.align+                (   keyword "merge"+                <>  Pretty.hardline+                <>  Pretty.indent 2 (prettyImportExpression_ a)+                <>  Pretty.hardline+                <>  Pretty.indent 2 (prettyImportExpression_ b)+                <>  Pretty.hardline+                <>  colon <> space+                <>  prettyExpression c+                )++        short = keyword "merge" <> space+            <>  prettyImportExpression_ a+            <>  " "+            <>  prettyImportExpression_ b+            <>  space <> colon <> space+            <>  prettyExpression c+    prettyAnnotatedExpression (ToMap a (Just b)) =+        Pretty.group (Pretty.flatAlt long short)+      where+        long =+            Pretty.align+                (   keyword "toMap"+                <>  Pretty.hardline+                <>  Pretty.indent 2 (prettyImportExpression_ a)+                <>  Pretty.hardline+                <>  colon <> space+                <>  prettyExpression b+                )++        short = keyword "toMap" <> space+            <>  prettyImportExpression_ a+            <>  space <> colon <> space+            <>  prettyExpression b+    prettyAnnotatedExpression a0@(Annot _ _) =+        enclose'+            ""+            "  "+            (" " <> colon <> " ")+            (colon <> space)+            (fmap duplicate (docs a0))+      where+        docs (Annot a b) = prettyOperatorExpression a : docs b+        docs a+            | Just doc <- preserveSource a =+                [ doc ]+            | Note _ b <- a =+                docs b+            | otherwise =+                [ prettyExpression a ]+    prettyAnnotatedExpression (ListLit (Just a) b) =+            list (map prettyExpression (Data.Foldable.toList b))+        <>  " : "+        <>  prettyExpression a+    prettyAnnotatedExpression a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettyAnnotatedExpression b+        | otherwise =+            prettyOperatorExpression a++    prettyOperatorExpression :: Pretty a => Expr Src a -> Doc Ann+    prettyOperatorExpression = prettyEquivalentExpression++    prettyOperator :: Text -> [Doc Ann] -> Doc Ann+    prettyOperator op docs =+        enclose'+            ""+            prefix+            (" " <> operator (Pretty.pretty op) <> " ")+            (operator (Pretty.pretty op) <> spacer)+            (reverse (fmap duplicate docs))+      where+        prefix = if Text.length op == 1 then "  " else "    "++        spacer = if Text.length op == 1 then " "  else "  "++    prettyEquivalentExpression :: Pretty a => Expr Src a -> Doc Ann+    prettyEquivalentExpression a0@(Equivalent _ _ _) =+        prettyOperator (equivalent characterSet) (docs a0)+      where+        docs (Equivalent _ a b) = prettyImportAltExpression b : docs a+        docs a+            | Just doc <- preserveSource a =+                [ doc ]+            | Note _ b <- a =+                docs b+            | otherwise =+                [ prettyImportAltExpression a ]+    prettyEquivalentExpression a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettyEquivalentExpression b+        | otherwise =+            prettyImportAltExpression a++    prettyImportAltExpression :: Pretty a => Expr Src a -> Doc Ann+    prettyImportAltExpression a0@(ImportAlt _ _) =+        prettyOperator "?" (docs a0)+      where+        docs (ImportAlt a b) = prettyOrExpression b : docs a+        docs a+            | Just doc <- preserveSource a =+                [ doc ]+            | Note _ b <- a =+                docs b+            | otherwise =+                [ prettyOrExpression a ]+    prettyImportAltExpression a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettyImportAltExpression b+        | otherwise =+            prettyOrExpression a++    prettyOrExpression :: Pretty a => Expr Src a -> Doc Ann+    prettyOrExpression a0@(BoolOr _ _) =+        prettyOperator "||" (docs a0)+      where+        docs (BoolOr a b) = prettyPlusExpression b : docs a+        docs a+            | Just doc <- preserveSource a =+                [ doc ]+            | Note _ b <- a =+                docs b+            | otherwise =+                [ prettyPlusExpression a ]+    prettyOrExpression a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettyOrExpression b+        | otherwise =+            prettyPlusExpression a++    prettyPlusExpression :: Pretty a => Expr Src a -> Doc Ann+    prettyPlusExpression a0@(NaturalPlus _ _) =+        prettyOperator "+" (docs a0)+      where+        docs (NaturalPlus a b) = prettyTextAppendExpression b : docs a+        docs a+            | Just doc <- preserveSource a =+                [ doc ]+            | Note _ b <- a =+                docs b+            | otherwise =+                [ prettyTextAppendExpression a ]+    prettyPlusExpression a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettyPlusExpression b+        | otherwise =+            prettyTextAppendExpression a++    prettyTextAppendExpression :: Pretty a => Expr Src a -> Doc Ann+    prettyTextAppendExpression a0@(TextAppend _ _) =+        prettyOperator "++" (docs a0)+      where+        docs (TextAppend a b) = prettyListAppendExpression b : docs a+        docs a+            | Just doc <- preserveSource a =+                [ doc ]+            | Note _ b <- a =+                docs b+            | otherwise =+                [ prettyListAppendExpression a ]+    prettyTextAppendExpression a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettyTextAppendExpression b+        | otherwise =+            prettyListAppendExpression a++    prettyListAppendExpression :: Pretty a => Expr Src a -> Doc Ann+    prettyListAppendExpression a0@(ListAppend _ _) =+        prettyOperator "#" (docs a0)+      where+        docs (ListAppend a b) = prettyAndExpression b : docs a+        docs a+            | Just doc <- preserveSource a =+                [ doc ]+            | Note _ b <- a =+                docs b+            | otherwise =+                [ prettyAndExpression a ]+    prettyListAppendExpression a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettyListAppendExpression b+        | otherwise =+            prettyAndExpression a++    prettyAndExpression :: Pretty a => Expr Src a -> Doc Ann+    prettyAndExpression a0@(BoolAnd _ _) =+        prettyOperator "&&" (docs a0)+      where+        docs (BoolAnd a b) = prettyCombineExpression b : docs a+        docs a+            | Just doc <- preserveSource a =+                [ doc ]+            | Note _ b <- a =+                docs b+            | otherwise =+                [ prettyCombineExpression a ]+    prettyAndExpression a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettyAndExpression b+        | otherwise =+            prettyCombineExpression a++    prettyCombineExpression :: Pretty a => Expr Src a -> Doc Ann+    prettyCombineExpression a0@(Combine _ _ _ _) =+        prettyOperator (combine characterSet) (docs a0)+      where+        docs (Combine _ _ a b) = prettyPreferExpression b : docs a+        docs a+            | Just doc <- preserveSource a =+                [ doc ]+            | Note _ b <- a =+                docs b+            | otherwise =+                [ prettyPreferExpression a ]+    prettyCombineExpression a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettyCombineExpression b+        | otherwise =+            prettyPreferExpression a++    prettyPreferExpression :: Pretty a => Expr Src a -> Doc Ann+    prettyPreferExpression a0@(Prefer {}) =+        prettyOperator (prefer characterSet) (docs a0)+      where+        docs (Prefer _ _ a b) = prettyCombineTypesExpression b : docs a+        docs a+            | Just doc <- preserveSource a =+                [ doc ]+            | Note _ b <- a =+                docs b+            | otherwise =+                [ prettyCombineTypesExpression a ]+    prettyPreferExpression a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettyPreferExpression b+        | otherwise =+            prettyCombineTypesExpression a++    prettyCombineTypesExpression :: Pretty a => Expr Src a -> Doc Ann+    prettyCombineTypesExpression a0@(CombineTypes _ _ _) =+        prettyOperator (combineTypes characterSet) (docs a0)+      where+        docs (CombineTypes _ a b) = prettyTimesExpression b : docs a+        docs a+            | Just doc <- preserveSource a =+                [ doc ]+            | Note _ b <- a =+                docs b+            | otherwise =+                [ prettyTimesExpression a ]+    prettyCombineTypesExpression a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettyCombineTypesExpression b+        | otherwise =+            prettyTimesExpression a++    prettyTimesExpression :: Pretty a => Expr Src a -> Doc Ann+    prettyTimesExpression a0@(NaturalTimes _ _) =+        prettyOperator "*" (docs a0)+      where+        docs (NaturalTimes a b) = prettyEqualExpression b : docs a+        docs a+            | Just doc <- preserveSource a =+                [ doc ]+            | Note _ b <- a =+                docs b+            | otherwise =+                [ prettyEqualExpression a ]+    prettyTimesExpression a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettyTimesExpression b+        | otherwise =+            prettyEqualExpression a++    prettyEqualExpression :: Pretty a => Expr Src a -> Doc Ann+    prettyEqualExpression a0@(BoolEQ _ _) =+        prettyOperator "==" (docs a0)+      where+        docs (BoolEQ a b) = prettyNotEqualExpression b : docs a+        docs a+            | Just doc <- preserveSource a =+                [ doc ]+            | Note _ b <- a =+                docs b+            | otherwise =+                [ prettyNotEqualExpression a ]+    prettyEqualExpression a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettyEqualExpression b+        | otherwise =+            prettyNotEqualExpression a++    prettyNotEqualExpression :: Pretty a => Expr Src a -> Doc Ann+    prettyNotEqualExpression a0@(BoolNE _ _) =+        prettyOperator "!=" (docs a0)+      where+        docs (BoolNE a b) = prettyApplicationExpression b : docs a+        docs a+            | Just doc <- preserveSource a =+                [ doc ]+            | Note _ b <- a =+                docs b+            | otherwise =+                [ prettyApplicationExpression a ]+    prettyNotEqualExpression a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettyNotEqualExpression b+        | otherwise =+            prettyApplicationExpression a++    prettyApplicationExpression :: Pretty a => Expr Src a -> Doc Ann+    prettyApplicationExpression = go []+      where+        go args = \case+            App a b           -> go (b : args) a+            Some a            -> app (builtin "Some") (a : args)+            Merge a b Nothing -> app (keyword "merge") (a : b : args)+            ToMap a Nothing   -> app (keyword "toMap") (a : args)+            ShowConstructor a -> app (keyword "showConstructor") (a : args)+            e | Note _ b <- e ->+                  go args b+              | null args ->+                  prettyImportExpression_ e -- just a performance optimization+              | Just doc <- preserveSource e ->+                  app doc args+              | otherwise ->+                  app (prettyImportExpression_ e) args++        app f args =+            enclose'+                "" "" " " ""+                ( duplicate f+                : map (fmap (Pretty.indent 2) . duplicate . prettyImportExpression_) args+                )++    prettyImportExpression_ :: Pretty a => Expr Src a -> Doc Ann+    prettyImportExpression_ (Embed a) =+        Pretty.pretty a+    prettyImportExpression_ a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettyImportExpression_ b+        | otherwise =+            prettyCompletionExpression a++    prettyCompletionExpression :: Pretty a => Expr Src a -> Doc Ann+    prettyCompletionExpression (RecordCompletion a b) =+        case shallowDenote b of+            RecordLit kvs ->+                Pretty.align+                    (   prettySelectorExpression a+                    <>  doubleColon+                    <>  prettyCompletionLit 0 kvs+                    )+            _ ->    prettySelectorExpression a+                <>  doubleColon+                <>  prettySelectorExpression b+    prettyCompletionExpression a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettyCompletionExpression b+        | otherwise =+            prettySelectorExpression a++    prettySelectorExpression :: Pretty a => Expr Src a -> Doc Ann+    prettySelectorExpression (Field a (Dhall.Syntax.fieldSelectionLabel -> b)) =+        prettySelectorExpression a <> dot <> prettyAnyLabel b+    prettySelectorExpression (Project a (Left b)) =+        prettySelectorExpression a <> dot <> prettyLabels b+    prettySelectorExpression (Project a (Right b)) =+            prettySelectorExpression a+        <>  dot+        <>  lparen+        <>  prettyExpression b+        <>  rparen+    prettySelectorExpression a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettySelectorExpression b+        | otherwise =+            prettyPrimitiveExpression a++    prettyPrimitiveExpression :: Pretty a => Expr Src a -> Doc Ann+    prettyPrimitiveExpression (Var a) =+        prettyVar a+    prettyPrimitiveExpression (Const k) =+        prettyConst k+    prettyPrimitiveExpression Bool =+        builtin "Bool"+    prettyPrimitiveExpression Bytes =+        builtin "Bytes"+    prettyPrimitiveExpression Natural =+        builtin "Natural"+    prettyPrimitiveExpression NaturalFold =+        builtin "Natural/fold"+    prettyPrimitiveExpression NaturalBuild =+        builtin "Natural/build"+    prettyPrimitiveExpression NaturalIsZero =+        builtin "Natural/isZero"+    prettyPrimitiveExpression NaturalEven =+        builtin "Natural/even"+    prettyPrimitiveExpression NaturalOdd =+        builtin "Natural/odd"+    prettyPrimitiveExpression NaturalToInteger =+        builtin "Natural/toInteger"+    prettyPrimitiveExpression NaturalShow =+        builtin "Natural/show"+    prettyPrimitiveExpression NaturalSubtract =+        builtin "Natural/subtract"+    prettyPrimitiveExpression Integer =+        builtin "Integer"+    prettyPrimitiveExpression IntegerClamp =+        builtin "Integer/clamp"+    prettyPrimitiveExpression IntegerNegate =+        builtin "Integer/negate"+    prettyPrimitiveExpression IntegerShow =+        builtin "Integer/show"+    prettyPrimitiveExpression IntegerToDouble =+        builtin "Integer/toDouble"+    prettyPrimitiveExpression Double =+        builtin "Double"+    prettyPrimitiveExpression DoubleShow =+        builtin "Double/show"+    prettyPrimitiveExpression Text =+        builtin "Text"+    prettyPrimitiveExpression TextReplace =+        builtin "Text/replace"+    prettyPrimitiveExpression TextShow =+        builtin "Text/show"+    prettyPrimitiveExpression Date =+        builtin "Date"+    prettyPrimitiveExpression (DateLiteral day) =+        literal+            (   Pretty.pretty (Printf.printf "%04d" _HHHH :: String)+            <>  "-"+            <>  Pretty.pretty (Printf.printf "%02d" _MM :: String)+            <>  "-"+            <>  Pretty.pretty (Printf.printf "%02d" _DD :: String)+            )+      where+        (_HHHH, _MM, _DD) = Time.toGregorian day+    prettyPrimitiveExpression DateShow =+        builtin "Date/show"+    prettyPrimitiveExpression Time =+        builtin "Time"+    prettyPrimitiveExpression (TimeLiteral (Time.TimeOfDay hh mm seconds) precision) =+        literal+            (   Pretty.pretty (Printf.printf "%02d" hh :: String)+            <>  ":"+            <>  Pretty.pretty (Printf.printf "%02d" mm :: String)+            <>  ":"+            <>  Pretty.pretty (Printf.printf "%02d" ss :: String)+            <>  suffix+            )+      where+        magnitude :: Integer+        magnitude = 10 ^ precision++        (ss, fraction) = truncate (seconds * fromInteger magnitude) `divMod` magnitude++        suffix+            | precision == 0 = ""+            | otherwise      = "." <> Pretty.pretty (Printf.printf "%0*d" precision fraction :: String)+    prettyPrimitiveExpression TimeShow =+        builtin "Time/show"+    prettyPrimitiveExpression TimeZone =+        builtin "TimeZone"+    prettyPrimitiveExpression (TimeZoneLiteral (Time.TimeZone minutes _ _)) =+        literal+            (   sign+            <>  Pretty.pretty (Printf.printf "%02d" _HH :: String)+            <>  ":"+            <>  Pretty.pretty (Printf.printf "%02d" _MM :: String)+            )+      where+        sign = if 0 <= minutes then "+" else "-"++        (_HH, _MM) = abs minutes `divMod` 60+    prettyPrimitiveExpression TimeZoneShow =+        builtin "TimeZone/show"+    prettyPrimitiveExpression List =+        builtin "List"+    prettyPrimitiveExpression ListBuild =+        builtin "List/build"+    prettyPrimitiveExpression ListFold =+        builtin "List/fold"+    prettyPrimitiveExpression ListLength =+        builtin "List/length"+    prettyPrimitiveExpression ListHead =+        builtin "List/head"+    prettyPrimitiveExpression ListLast =+        builtin "List/last"+    prettyPrimitiveExpression ListIndexed =+        builtin "List/indexed"+    prettyPrimitiveExpression ListReverse =+        builtin "List/reverse"+    prettyPrimitiveExpression Optional =+        builtin "Optional"+    prettyPrimitiveExpression None =+        builtin "None"+    prettyPrimitiveExpression (BoolLit True) =+        builtin "True"+    prettyPrimitiveExpression (BoolLit False) =+        builtin "False"+    prettyPrimitiveExpression (IntegerLit a)+        | 0 <= a    = literal "+" <> prettyNumber a+        | otherwise = prettyNumber a+    prettyPrimitiveExpression (NaturalLit a) =+        prettyNatural a+    prettyPrimitiveExpression (DoubleLit (DhallDouble a)) =+        prettyDouble a+    prettyPrimitiveExpression (TextLit a) =+        prettyChunks a+    prettyPrimitiveExpression (BytesLit a) =+        prettyBytes a+    prettyPrimitiveExpression (Record a) =+        prettyRecord a+    prettyPrimitiveExpression (RecordLit a) =+        prettyRecordLit a+    prettyPrimitiveExpression (Union a) =+        prettyUnion a+    prettyPrimitiveExpression (ListLit Nothing b) =+        list (map prettyExpression (Data.Foldable.toList b))+    prettyPrimitiveExpression a+        | Just doc <- preserveSource a =+            doc+        | Note _ b <- a =+            prettyPrimitiveExpression b+        | otherwise =+            Pretty.group (Pretty.flatAlt long short)+      where+        long =+            Pretty.align+                (lparen <> space <> prettyExpression a <> Pretty.hardline <> rparen)++        short = lparen <> prettyExpression a <> rparen++    prettyKeyValue+        :: Pretty a+        => (key -> Doc Ann)+        -> (Expr Src a -> Doc Ann)+        -> Doc Ann+        -> KeyValue key Src a+        -> (Doc Ann, Doc Ann)+    prettyKeyValue prettyKey prettyValue separator (KeyValue key mSrc val) =+        duplicate (Pretty.group (Pretty.flatAlt long short))+      where+        completion _T r =+                prettySelectorExpression _T+            <>  doubleColon+            <>  case shallowDenote r of+                    RecordLit kvs ->+                        prettyCompletionLit 2 kvs+                    _ ->+                        prettySelectorExpression r++        short = prettyKeys prettyKey key+            <>  " "+            <>  separator+            <>  " "+            <>  case renderSrcMaybe mSrc of+                    Nothing  -> mempty+                    Just doc -> doc <> Pretty.hardline+            <>  prettyValue val++        long =  Pretty.align+                    (   prettyKeys prettyKey key+                    <>  preSeparator+                    )+            <>  separator+            <>  case renderSrcMaybe mSrc of+                    Just doc ->+                            preComment+                        <>  Pretty.align+                                (   doc+                                <>  Pretty.hardline+                                <>  prettyValue val+                                )+                    Nothing ->+                        case shallowDenote val of+                            Some val' ->+                                    " "+                                <>  builtin "Some"+                                <>  case shallowDenote val' of+                                        RecordCompletion _T r ->+                                                " "+                                            <>  completion _T r++                                        RecordLit _ ->+                                                Pretty.hardline+                                            <>  "  "+                                            <>  prettyImportExpression_ val'++                                        ListLit _ xs+                                            | not (null xs) ->+                                                    Pretty.hardline+                                                <>  "  "+                                                <>  prettyImportExpression_ val'++                                        _ ->    Pretty.hardline+                                            <>  "    "+                                            <>  prettyImportExpression_ val'++                            ToMap val' Nothing ->+                                    " "+                                <>  keyword "toMap"+                                <>  case shallowDenote val' of+                                        RecordCompletion _T r ->+                                                " "+                                            <>  completion _T r+                                        _ ->    Pretty.hardline+                                            <>  "    "+                                            <>  prettyImportExpression_ val'++                            ShowConstructor val' ->+                                    " "+                                <>  keyword "showConstructor"+                                <>  case shallowDenote val' of+                                        RecordCompletion _T r ->+                                                " "+                                            <>  completion _T r+                                        _ ->    Pretty.hardline+                                            <>  "    "+                                            <>  prettyImportExpression_ val'++                            RecordCompletion _T r ->+                                " " <> completion _T r++                            RecordLit _ ->+                                    Pretty.hardline+                                <>  "  "+                                <>  prettyValue val++                            ListLit _ xs+                                | not (null xs) ->+                                        Pretty.hardline+                                    <>  "  "+                                    <>  prettyValue val++                            _ ->+                                Pretty.group+                                    (   Pretty.flatAlt (Pretty.hardline <> "    ") " "+                                    <>  prettyValue val+                                    )+          where+            (preSeparator, preComment) =+                case key of+                    (_, _, mSrc2) :| [] | not (containsComment mSrc2) ->+                        (" ", Pretty.hardline <> "    ")+                    _ ->+                        (Pretty.hardline, " ")+++    prettyRecord :: Pretty a => Map Text (RecordField Src a) -> Doc Ann+    prettyRecord =+        ( braces+        . map (prettyKeyValue prettyAnyLabelOrSome prettyExpression colon . adapt)+        . Map.toList+        )+      where+        adapt (key, RecordField mSrc0 val mSrc1 mSrc2) = KeyValue (pure (mSrc0, key, mSrc1)) mSrc2 val++    prettyRecordLit :: Pretty a => Map Text (RecordField Src a) -> Doc Ann+    prettyRecordLit m+        | [ ("date"    , field -> d@DateLiteral{})+          , ("time"    , field -> t@TimeLiteral{})+          , ("timeZone", field -> z@TimeZoneLiteral{})+          ] <- List.sortOn fst (Map.toList m) =+              literal+                  (   prettyPrimitiveExpression d+                  <>  "T"+                  <>  prettyPrimitiveExpression t+                  <>  prettyPrimitiveExpression z+                  )+        | [ ("date"    , field -> d@DateLiteral{})+          , ("time"    , field -> t@TimeLiteral{})+          ] <- List.sortOn fst (Map.toList m) =+              literal+                  (   prettyPrimitiveExpression d+                  <>  "T"+                  <>  prettyPrimitiveExpression t+                  )+        | [ ("time"    , field -> t@TimeLiteral{})+          , ("timeZone", field -> z@TimeZoneLiteral{})+          ] <- List.sortOn fst (Map.toList m) =+              literal+                  (   prettyPrimitiveExpression t+                  <>  prettyPrimitiveExpression z+                  )+      where+        field = Dhall.Syntax.shallowDenote . recordFieldValue+    prettyRecordLit m = prettyRecordLike braces m++    prettyCompletionLit :: Pretty a => Int -> Map Text (RecordField Src a) -> Doc Ann+    prettyCompletionLit = prettyRecordLike . hangingBraces++    prettyRecordLike+        :: Pretty a+        => ([(Doc Ann, Doc Ann)] -> Doc Ann)+        -> Map Text (RecordField Src a)+        -> Doc Ann+    prettyRecordLike braceStyle a+        | Data.Foldable.null a =+            lbrace <> equals <> rbrace+        | otherwise =+            braceStyle (map prettyRecordEntry (consolidateRecordLiteral a))+      where+        prettyRecordEntry kv@(KeyValue keys mSrc2 val) =+            case keys of+                (mSrc0, key, mSrc1) :| []+                    | Var (V key' 0) <- Dhall.Syntax.shallowDenote val+                    , key == key'+                    , not (containsComment mSrc2) ->+                        duplicate (prettyKeys prettyAnyLabelOrSome [(mSrc0, key, mSrc1)])+                _ ->+                    prettyKeyValue prettyAnyLabelOrSome prettyExpression equals kv++    prettyAlternative (key, Just val) =+        prettyKeyValue prettyAnyLabelOrSome prettyExpression colon (makeKeyValue (pure key) val)+    prettyAlternative (key, Nothing) =+        duplicate (prettyAnyLabelOrSome key)++    prettyUnion :: Pretty a => Map Text (Maybe (Expr Src a)) -> Doc Ann+    prettyUnion =+        angles . map prettyAlternative . Map.toList++    prettyBytes :: ByteString -> Doc Ann+    prettyBytes bytes =+        literal (Pretty.pretty ("0x\"" <> prettyBase16 bytes <> "\""))++    prettyChunks :: Pretty a => Chunks Src a -> Doc Ann+    prettyChunks chunks@(Chunks a b)+        | anyText (== '\n') =+            if not (null a) || anyText (/= '\n')+            then long+            else Pretty.group (Pretty.flatAlt long short)+        | otherwise =+            short+      where+        long =+            Pretty.align+            (   literal "''" <> Pretty.hardline+            <>  Pretty.align+                (foldMap prettyMultilineChunk a' <> prettyMultilineText b')+            <>  literal "''"+            )+          where+            Chunks a' b' = multilineChunks chunks++        short =+            literal "\"" <> foldMap prettyChunk a <> literal (prettyText b <> "\"")++        anyText predicate = any (\(text, _) -> Text.any predicate text) a || Text.any predicate b++        prettyMultilineChunk (c, d) =+                prettyMultilineText c+            <>  dollar+            <>  lbrace+            <>  prettyExpression d+            <>  rbrace++        prettyMultilineText text = mconcat docs+          where+            lines_ = Text.splitOn "\n" text++            -- Annotate only non-empty lines so trailing whitespace can be+            -- removed on empty ones.+            prettyLine line =+                (if Text.null line then id else literal)+                    (Pretty.pretty line)++            docs = List.intersperse Pretty.hardline (map prettyLine lines_)++        prettyChunk (c, d) =+                prettyText c+            <>  syntax "${"+            <>  prettyExpression d+            <>  syntax rbrace++        prettyText t = literal (Pretty.pretty (escapeText_ t))+++-- | Prepare 'Chunks' for multi-line formatting by escaping problematic+-- character sequences via string interpolations+--+-- >>> multilineChunks (Chunks [] "\n \tx")+-- Chunks [("\n",TextLit (Chunks [] " \t"))] "x"+-- >>> multilineChunks (Chunks [] "\n\NUL\b\f\t")+-- Chunks [("\n",TextLit (Chunks [] "\NUL\b\f"))] "\t"+multilineChunks :: Chunks s a -> Chunks s a+multilineChunks =+     escapeSingleQuotedText+   . escapeTrailingSingleQuote+   . escapeControlCharacters+   . escapeSingleQuoteBeforeInterpolation+   . escapeSharedWhitespacePrefix++-- | Escape any leading whitespace shared by all lines+--+-- This ensures that significant shared leading whitespace is not stripped+--+-- >>> escapeSharedWhitespacePrefix (Chunks [] "\n \tx")+-- Chunks [("\n",TextLit (Chunks [] " \t"))] "x"+-- >>> escapeSharedWhitespacePrefix (Chunks [("\n",Var (V "x" 0))] " ")+-- Chunks [("\n",Var (V "x" 0))] " "+-- >>> escapeSharedWhitespacePrefix (Chunks [("\n ",Var (V "x" 0))] "")+-- Chunks [("\n",TextLit (Chunks [] " ")),("",Var (V "x" 0))] ""+-- >>> escapeSharedWhitespacePrefix (Chunks [("\n ",Var (V "x" 0))] "\n")+-- Chunks [("\n ",Var (V "x" 0))] "\n"+-- >>> escapeSharedWhitespacePrefix (Chunks [] " ")+-- Chunks [("",TextLit (Chunks [] " "))] ""+escapeSharedWhitespacePrefix :: Chunks s a -> Chunks s a+escapeSharedWhitespacePrefix literal_ = unlinesLiteral literals₁+  where+    literals₀ = linesLiteral literal_++    sharedPrefix = longestSharedWhitespacePrefix literals₀++    stripPrefix = Text.drop (Text.length sharedPrefix)++    escapeSharedPrefix (Chunks [] prefix₀)+        | Text.isPrefixOf sharedPrefix prefix₀ =+            Chunks [ ("", TextLit (Chunks [] sharedPrefix)) ] prefix₁+      where+        prefix₁ = stripPrefix prefix₀+    escapeSharedPrefix (Chunks ((prefix₀, y) : xys) z)+        | Text.isPrefixOf sharedPrefix prefix₀ =+            Chunks (("", TextLit (Chunks [] sharedPrefix)) : (prefix₁, y) : xys) z+      where+        prefix₁ = stripPrefix prefix₀+    escapeSharedPrefix line = line++    literals₁+        | not (Text.null sharedPrefix) = fmap escapeSharedPrefix literals₀+        | otherwise = literals₀++-- | Escape control characters by moving them into string interpolations+--+-- >>> escapeControlCharacters (Chunks [] "\n\NUL\b\f\t")+-- Chunks [("\n",TextLit (Chunks [] "\NUL\b\f"))] "\t"+escapeControlCharacters :: Chunks s a -> Chunks s a+escapeControlCharacters = splitWith (splitOnPredicate predicate)+  where+    predicate c = Data.Char.isControl c && c /= ' ' && c /= '\t' && c /= '\n'++-- | Escape @'${@ correctly+--+-- See: https://github.com/dhall-lang/dhall-haskell/issues/2078+escapeSingleQuoteBeforeInterpolation :: Chunks s a -> Chunks s a+escapeSingleQuoteBeforeInterpolation = splitWith f+  where+    f text =+        case Text.splitOn "'${" text of+            -- `splitOn` should never return an empty list, but just in case…+            []     -> mempty+            t : ts -> loop t ts++    loop head_ tail_ =+        case tail_ of+            [] ->+                Chunks [] head_+            newHead : newTail ->+                    Chunks [ (head_, TextLit (Chunks [] "'")) ] "${"+                <>  loop newHead newTail++{-| You can think of this as sort of like `concatMap` for `Chunks`++    Given a function that splits plain text into interpolated chunks, apply+    that function to each uninterpolated span to yield a new+    possibly-interpolated span, and flatten the results.+-}+splitWith :: (Text -> Chunks s a) -> Chunks s a -> Chunks s a+splitWith splitter (Chunks xys z) = mconcat (xys' ++ [ splitter z ])+  where+    xys' = do+        (x, y) <- xys++        [ splitter x, Chunks [ ("", y) ] "" ]++-- | Split `Data.Text.Text` into interpolated chunks, where all characters+-- matching the predicate are pushed into a string interpolation.+--+-- >>> splitOnPredicate (== 'x') ""+-- Chunks [] ""+-- >>> splitOnPredicate (== 'x') " xx "+-- Chunks [(" ",TextLit (Chunks [] "xx"))] " "+-- >>> splitOnPredicate (== 'x') "xx"+-- Chunks [("",TextLit (Chunks [] "xx"))] ""+--+-- prop> \(Fun _ p) s -> let {t = Text.pack s; Chunks xys z = splitOnPredicate p t} in foldMap (\(x, TextLit (Chunks [] y)) -> x <> y) xys <> z == t+splitOnPredicate :: (Char -> Bool) -> Text -> Chunks s a+splitOnPredicate predicate text+    | Text.null b =+        Chunks [] a+    | otherwise =+        Chunks ((a, TextLit (Chunks [] c)) : e) f+  where+    (a, b) = Text.break predicate text++    (c, d) = Text.span predicate b++    Chunks e f = splitOnPredicate predicate d++-- | Escape a trailing single quote by moving it into a string interpolation+--+-- Otherwise the multiline-string would end with @'''@, which would be parsed+-- as an escaped @''@.+--+-- >>> escapeTrailingSingleQuote (Chunks [] "\n'")+-- Chunks [("\n",TextLit (Chunks [] "'"))] ""+escapeTrailingSingleQuote :: Chunks s a -> Chunks s a+escapeTrailingSingleQuote chunks@(Chunks as b) =+    case Text.unsnoc b of+        Just (b', '\'') -> Chunks (as ++ [(b', TextLit (Chunks [] "'"))]) ""+        _               -> chunks++-- | Pretty-print a value+pretty_ :: Pretty a => a -> Text+pretty_ = prettyToStrictText++data KeyValue k s a = KeyValue+    { _keyValueKeys  :: NonEmpty (Maybe s, k , Maybe s)+    , _keyValueSrc   :: Maybe s+    , _keyValueValue :: Expr s a+    }++makeKeyValue :: NonEmpty key -> Expr s a -> KeyValue key s a+makeKeyValue keys expr = KeyValue (adapt <$> keys) Nothing expr+  where+    adapt key = (Nothing, key, Nothing)++{- This utility function converts+   `{ x = { y = { z = 1 } } }` to `{ x.y.z = 1 }`+-}+consolidateRecordLiteral+    :: Map Text (RecordField Src a) -> [KeyValue Text Src a]+consolidateRecordLiteral = concatMap adapt . Map.toList+  where+    adapt :: (Text, RecordField Src a) -> [KeyValue Text Src a]+    adapt (key, RecordField mSrc0 val mSrc1 mSrc2)+        | not (containsComment mSrc2)+        , RecordLit m <- e+        , [ KeyValue keys mSrc2' val' ] <- concatMap adapt (Map.toList m) =+            [ KeyValue (NonEmpty.cons (mSrc0, key, mSrc1) keys) mSrc2' val' ]++        | Combine _ (Just _) l r <- e =+            adapt (key, makeRecordField l) <> adapt (key, makeRecordField r)+        | otherwise =+            [ KeyValue (pure (mSrc0, key, mSrc1)) mSrc2 val ]+      where+        e = shallowDenote val++-- | Escape a `Data.Text.Text` literal using Dhall's escaping rules for+--   single-quoted @Text@+escapeSingleQuotedText :: Chunks s a -> Chunks s a+escapeSingleQuotedText = splitWith f+  where+    f inputText = Chunks [] outputText+      where+        outputText =+            Text.replace "${" "''${" (Text.replace "''" "'''" inputText)++{-| Escape a `Data.Text.Text` literal using Dhall's escaping rules++    Note that the result does not include surrounding quotes+-}+escapeText_ :: Text -> Text+escapeText_ text = Text.concatMap adapt text+  where+    adapt c+        | '\x20' <= c && c <= '\x21'     = Text.singleton c+        -- '\x22' == '"'+        | '\x23' == c                    = Text.singleton c+        -- '\x24' == '$'+        | '\x25' <= c && c <= '\x5B'     = Text.singleton c+        -- '\x5C' == '\\'+        | '\x5D' <= c && c <= '\x10FFFF' = Text.singleton c+        | c == '"'                       = "\\\""+        | c == '$'                       = "\\$"+        | c == '\\'                      = "\\\\"+        | c == '\b'                      = "\\b"+        | c == '\f'                      = "\\f"+        | c == '\n'                      = "\\n"+        | c == '\r'                      = "\\r"+        | c == '\t'                      = "\\t"+        | otherwise                      = "\\u" <> showDigits (Data.Char.ord c)++    showDigits r0 = Text.pack (map showDigit [q1, q2, q3, r3])+      where+        (q1, r1) = r0 `quotRem` 4096+        (q2, r2) = r1 `quotRem`  256+        (q3, r3) = r2 `quotRem`   16++    showDigit n+        | n < 10    = Data.Char.chr (Data.Char.ord '0' + n)+        | otherwise = Data.Char.chr (Data.Char.ord 'A' + n - 10)++prettyToString :: Pretty a => a -> String+prettyToString =+    Pretty.renderString . layout . Pretty.pretty++docToStrictText :: Doc ann -> Text.Text+docToStrictText = Pretty.renderStrict . layout++prettyToStrictText :: Pretty a => a -> Text.Text+prettyToStrictText = docToStrictText . Pretty.pretty++-- | Layout using 'layoutOpts'+--+-- Tries hard to fit the document into 80 columns.+--+-- This also removes trailing space characters (@' '@) /unless/+-- they are enclosed in an annotation.+layout :: Pretty.Doc ann -> Pretty.SimpleDocStream ann+layout = Pretty.removeTrailingWhitespace . Pretty.layoutSmart layoutOpts++-- | Default layout options+layoutOpts :: Pretty.LayoutOptions+layoutOpts =+    Pretty.defaultLayoutOptions+        { Pretty.layoutPageWidth = Pretty.AvailablePerLine 80 1.0 }++{-| Convert an expression representing a temporal value to `Data.Text.Text`, if+    possible++    This is used by downstream integrations (e.g. `dhall-json` for treating+    temporal values as strings+-}+temporalToText :: Pretty a => Expr s a -> Maybe Text+temporalToText e = case e of+    RecordLit m+        | [ ("date"    , field -> DateLiteral{})+          , ("time"    , field -> TimeLiteral{})+          , ("timeZone", field -> TimeZoneLiteral{})+          ] <- List.sortOn fst (Map.toList m) -> rendered+        | [ ("date"    , field -> DateLiteral{})+          , ("time"    , field -> TimeLiteral{})+          ] <- List.sortOn fst (Map.toList m) -> rendered+        | [ ("time"    , field -> TimeLiteral{})+          , ("timeZone", field -> TimeZoneLiteral{})+          ] <- List.sortOn fst (Map.toList m) -> rendered+    DateLiteral{} -> rendered+    TimeLiteral{} -> rendered+    TimeZoneLiteral{} -> rendered+    _ -> Nothing+  where+    field = Dhall.Syntax.shallowDenote . recordFieldValue++    rendered = Just (prettyToStrictText e)++prettyBase16 :: ByteString -> Text+prettyBase16 bytes =+    case Encoding.decodeUtf8' (Base16.encode bytes) of+        Left exception ->+            Operations.internalError+                ("prettyBase16: base16-encoded bytes could not be decoded as UTF-8 text: " <> Text.pack (Exception.displayException exception))+        Right text ->+            Text.toUpper text++{- $setup+>>> import Test.QuickCheck (Fun(..))+-}
src/Dhall/Pretty/Internal.hs-boot view
@@ -1,18 +1,35 @@ 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.Core+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  prettyExpr :: Pretty a => Expr s a -> Doc Ann -pretty :: Pretty a => a -> Text+prettyEnvironmentVariable :: Text -> Doc ann -escapeText :: Text -> Text+prettyImportExpression :: Pretty a => Expr Src a -> Doc Ann
src/Dhall/Repl.hs view
@@ -1,88 +1,122 @@ -- | This module contains the implementation of the @dhall repl@ subcommand -{-# 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.List.NonEmpty (NonEmpty(..))-import Data.Maybe ( mapMaybe )-import Data.Semigroup ((<>))-import Data.Text ( Text )-import Dhall.Binary (StandardVersion(..))-import Dhall.Context (Context)-import Dhall.Import (hashExpressionToCode, standardVersion)-import Dhall.Pretty (CharacterSet(..))-import Lens.Family (set)-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.Binary import qualified Dhall.Context import qualified Dhall.Core-import qualified Dhall.Core as Dhall ( Var(V), Expr, normalize )+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.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.Pretty.Internal+import qualified Dhall.Syntax                        as Syntax+import qualified Dhall.TypeCheck                     as Dhall+import qualified Dhall.Version                       as Meta+import qualified Prettyprinter                       as Pretty+import qualified Prettyprinter.Render.Terminal       as Pretty (renderIO) import qualified System.Console.ANSI import qualified System.Console.Haskeline.Completion as Haskeline-import qualified System.Console.Haskeline.MonadException as Haskeline-import qualified System.Console.Repline as Repline+import qualified System.Console.Repline              as Repline import qualified System.IO+import qualified Text.Megaparsec                     as Megaparsec +#if MIN_VERSION_haskeline(0,8,0)+import qualified Control.Monad.Catch+#else+import qualified System.Console.Haskeline.MonadException+#endif+ type Repl = Repline.HaskelineT (State.StateT Env IO)  -- | Implementation of the @dhall repl@ subcommand-repl :: CharacterSet -> Bool -> StandardVersion -> IO ()-repl characterSet explain _standardVersion =+repl :: CharacterSet -> Bool -> IO ()+repl characterSet explain =     if explain then Dhall.detailed io else io   where     io =       evalStateT         ( Repline.evalRepl-            ( pure "⊢ " )+            banner             ( dontCrash . eval )             options             ( Just optionsPrefix )+            ( Just "paste" )             completer             greeter+            finaliser         )-        (emptyEnv { characterSet, explain, _standardVersion })+        (emptyEnv { characterSet, explain }) +    banner = pure . \case+      Repline.SingleLine -> turnstile <> " "+      Repline.MultiLine  -> "| " +    turnstile =+      case characterSet of+        Unicode -> "⊢"+        ASCII   -> "|-"+ data Env = Env   { envBindings      :: Dhall.Context.Context Binding   , envIt            :: Maybe Binding   , explain          :: Bool   , characterSet     :: CharacterSet-  , _standardVersion :: StandardVersion   , outputHandle     :: Maybe System.IO.Handle   } @@ -93,15 +127,14 @@     { envBindings = Dhall.Context.empty     , envIt = Nothing     , explain = False-    , _standardVersion = Dhall.Binary.defaultStandardVersion     , characterSet = Unicode     , outputHandle = Just System.IO.stdout     }   data Binding = Binding-  { bindingExpr :: Dhall.Expr Dhall.Src Dhall.X-  , bindingType :: Dhall.Expr Dhall.Src Dhall.X+  { bindingExpr :: Dhall.Expr Dhall.Src Void+  , bindingType :: Dhall.Expr Dhall.Src Void   }  @@ -116,22 +149,17 @@   parseAndLoad-  :: ( MonadIO m, MonadState Env m )-  => String -> m ( Dhall.Expr Dhall.Src Dhall.X )+  :: MonadIO m => String -> m ( Dhall.Expr Dhall.Src Void)  parseAndLoad src = do-  env <--    get-   parsed <--    case Dhall.exprFromText "(stdin)" ( Text.pack src ) of+    case Dhall.exprFromText "(input)" (Text.pack src <> "\n") of       Left e ->         liftIO ( throwIO e )        Right a ->         return a -  let status =-        set standardVersion (_standardVersion env) (Dhall.emptyStatus ".")+  let status = Dhall.emptyStatus "."    liftIO ( State.evalStateT (Dhall.loadWith parsed) status ) @@ -153,43 +181,34 @@   -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 -  exprType' <--    normalize exprType--  output exprType'+  output exprType   applyContext     :: Context Binding-    -> Dhall.Expr Dhall.Src Dhall.X-    -> Dhall.Expr Dhall.Src Dhall.X+    -> Dhall.Expr Dhall.Src Void+    -> Dhall.Expr Dhall.Src Void applyContext context expression =-  case bindings of-    []     -> expression-    b : bs -> Dhall.Core.Let (b :| bs) expression+    Dhall.Core.wrapInLets bindings expression   where     definitions = reverse $ Dhall.Context.toList context -    convertBinding (variable, Binding {..}) = Dhall.Core.Binding {..}-      where-        annotation = Just bindingType-        value      = bindingExpr+    convertBinding (variable, Binding expr _) =+        Dhall.Core.Binding Nothing variable Nothing Nothing Nothing expr      bindings = fmap convertBinding definitions  normalize   :: MonadState Env m-  => Dhall.Expr Dhall.Src Dhall.X -> m ( Dhall.Expr t Dhall.X )+  => Dhall.Expr Dhall.Src Void -> m ( Dhall.Expr t Void ) normalize e = do   env <- get @@ -198,7 +217,7 @@  typeCheck   :: ( MonadIO m, MonadState Env m )-  => Dhall.Expr Dhall.Src Dhall.X -> m ( Dhall.Expr Dhall.Src Dhall.X )+  => Dhall.Expr Dhall.Src Void -> m ( Dhall.Expr Dhall.Src Void ) typeCheck expression = do   env <- get @@ -208,68 +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-  let-    varName =-      Text.pack k+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 =+        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 -  Env{_standardVersion} <- get--  writeOutputHandle $ hashExpressionToCode _standardVersion normalizedExpression+  writeOutputHandle+    (hashExpressionToCode (Dhall.Core.alphaNormalize normalizedExpression))  saveFilePrefix :: FilePath saveFilePrefix = ".dhall-repl"@@ -306,27 +332,33 @@    pure $ saveFilePrefix <> "-" <> show nextIndex -loadBinding-  :: ( MonadFail m, MonadIO m, MonadState Env m, Haskeline.MonadException m )-  => [String] -> m ()-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@@ -335,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@@ -364,7 +394,11 @@       handler handle =           State.evalStateT             (forM_ bindings $ \(name, expr) -> do-              liftIO (System.IO.hPutStr handle $ ":let " <> Text.unpack name <> " = ")+              let doc = Dhall.Pretty.Internal.prettyLabel name++              let label = Dhall.Pretty.Internal.docToStrictText doc++              liftIO (System.IO.hPutStr handle $ ":let " <> Text.unpack label <> " = ")               outputWithoutSpacing expr)             (env { outputHandle = Just handle }) @@ -373,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 @@ -391,45 +425,114 @@    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 ()+help hs _ = do+  liftIO (putStrLn "Type any expression to normalize it or use one of the following commands:")+  forM_ hs $ \h -> do+    let name = helpOptionName h+        syntax = helpOptionSyntax h+        doc = helpOptionDoc h+    liftIO (putStrLn (":" <> name <> " " <> syntax))+    liftIO (putStrLn ("    " <> doc))  optionsPrefix :: Char optionsPrefix = ':' +trim :: String -> String+trim = dropWhile isSpace . dropWhileEnd isSpace -options-  :: ( Haskeline.MonadException m, MonadFail m, MonadIO m, MonadState Env m )-  => Repline.Options m-options =-  [ ( "type", dontCrash . typeOf )-  , ( "hash", dontCrash . hashBinding )-  , ( "let", dontCrash . addBinding . separateEqual )-  , ( "clear", dontCrash . clearBindings)-  , ( "load", dontCrash . loadBinding )-  , ( "save", dontCrash . saveBinding . separateEqual )-  , ( "set", dontCrash . setOption)-  , ( "unset", dontCrash . unsetOption)-  , ( "quit", cmdQuit )+data HelpOption m = HelpOption+  { helpOptionName :: String+  , helpOptionSyntax :: String+  , helpOptionDoc :: String+  , helpOptionFunction :: Repline.Cmd m+  }++type HelpOptions m = [HelpOption m]++helpOptions :: HelpOptions Repl+helpOptions =+  [ HelpOption+      "help"+      ""+      "Print help text and describe options"+      (dontCrash . help helpOptions)+  , HelpOption+      "paste"+      ""+      "Start a multi-line input. Submit with <Ctrl-D>"+      (error "Dhall.Repl.helpOptions: Unreachable")+  , HelpOption+      "type"+      "EXPRESSION"+      "Infer the type of an expression"+      (dontCrash . typeOf)+  , HelpOption+      "hash"+      "EXPRESSION"+      "Hash the normalized value of an expression"+      (dontCrash . hashBinding)+  , HelpOption+      "let"+      "IDENTIFIER = EXPRESSION"+      "Assign an expression to a variable"+      (dontCrash . addBinding)+  , HelpOption+      "clear"+      ""+      "Clear all bound variables"+      (dontCrash . clearBindings)+  , HelpOption+      "load"+      "[FILENAME]"+      "Load bound variables from a file"+      (dontCrash . loadBinding . trim)+  , HelpOption+      "save"+      "[FILENAME | FILENAME = EXPRESSION]"+      "Save bound variables or a given expression to a file"+      (dontCrash . saveBinding . parseAssignment)+  , HelpOption+      "set"+      "OPTION"+      "Set an option. Currently supported: --explain"+      (dontCrash . setOption . trim)+  , HelpOption+      "unset"+      "OPTION"+      "Unset an option"+      (dontCrash . unsetOption . trim)+  , HelpOption+      "quit"+      ""+      "Exit the REPL"+      cmdQuit   ] +options :: Repline.Options Repl+options = (\h -> (helpOptionName h, helpOptionFunction h)) <$> helpOptions  completer   :: (Monad m, MonadFail m, MonadIO m, MonadState Env m)@@ -493,7 +596,7 @@     listCompletion = map simpleCompletion . filter (word `isPrefixOf`)      algebraicComplete-        :: [Text.Text] -> Dhall.Expr Dhall.Src Dhall.X -> [Text.Text]+        :: [Text.Text] -> Dhall.Expr Dhall.Src Void -> [Text.Text]     algebraicComplete subFields expr =       let keys = fmap ("." <>) . Map.keys @@ -512,19 +615,29 @@                               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             _                         -> []   greeter :: MonadIO m => m () greeter =-  return ()+  let version = Meta.dhallVersionString+      message = "Welcome to the Dhall v" <> version <> " REPL! Type :help for more information."+  in liftIO (putStrLn message) +finaliser :: MonadIO m => m Repline.ExitDecision+finaliser = do+  liftIO (putStrLn quitMessage)+  pure Repline.Exit -dontCrash :: ( MonadIO m, Haskeline.MonadException m ) => m () -> m ()+dontCrash :: Repl () -> Repl () dontCrash m =-  Haskeline.catch+#if MIN_VERSION_haskeline(0,8,0)+  Control.Monad.Catch.catch+#else+  System.Console.Haskeline.MonadException.catch+#endif     m     ( \ e@SomeException{} -> liftIO ( putStrLn ( displayException e ) ) ) @@ -538,7 +651,7 @@  output   :: (Pretty.Pretty a, MonadState Env m, MonadIO m)-  => Dhall.Expr s a -> m ()+  => Dhall.Expr Src a -> m () output expr = do   writeOutputHandle "" -- Visual spacing @@ -548,16 +661,14 @@  outputWithoutSpacing   :: (Pretty.Pretty a, MonadState Env m, MonadIO m)-  => Dhall.Expr s a -> m ()+  => Dhall.Expr Src a -> m () outputWithoutSpacing expr = do   Env { characterSet, outputHandle } <- get    case outputHandle of     Nothing     -> pure ()     Just handle -> do-      let stream =-              Pretty.layoutSmart Dhall.Pretty.layoutOpts-                  (Dhall.Pretty.prettyCharacterSet characterSet expr)+      let stream = Dhall.Pretty.layout (Dhall.Pretty.prettyCharacterSet characterSet expr)        supportsANSI <- liftIO (System.Console.ANSI.hSupportsANSI handle)       let ansiStream =
+ 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,5 +1,7 @@+{-# LANGUAGE DeriveAnyClass     #-} {-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveGeneric      #-}+{-# LANGUAGE DeriveLift         #-}  -- | This module only exports ways of constructing a Set, -- retrieving List, Set, and Seq representations of the same data,@@ -9,51 +11,99 @@ module Dhall.Set (       Set(..)     , toList+    , toAscList     , toSet     , toSeq     , fromList+    , fromSet     , append     , empty     , difference+    , sort+    , isSorted+    , null+    , size     ) where -import Prelude-import Data.List (foldl')-import Data.Sequence (Seq, (|>))-import Data.Data (Data)-import GHC.Generics (Generic)+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+    formatting Dhall code+-} data Set a = Set (Data.Set.Set a) (Seq a)-    deriving (Eq, Generic, Ord, Show, Data)+    deriving (Generic, Show, Data, NFData, Lift)+-- Invariant: In @Set set seq@, @toAscList set == sort (toList seq)@. +instance Eq a => Eq (Set a) where+    (Set _ x) == (Set _ y) = x == y+    {-# INLINABLE (==) #-}++instance Ord a => Ord (Set a) where+    compare (Set _ x) (Set _ y) = compare x y+    {-# INLINABLE compare #-}+ instance Foldable Set where-    foldMap f = foldMap f . toSeq+    foldMap f (Set _ x) = foldMap f x+    {-# INLINABLE foldMap #-} +    toList = Dhall.Set.toList+    {-# INLINABLE toList #-}++    null = Dhall.Set.null+    {-# INLINABLE null #-}++    length = Dhall.Set.size+    {-# INLINABLE length #-}++-- | Convert to an unordered @"Data.Set".`Data.Set.Set`@ toSet :: Set a -> Data.Set.Set a toSet (Set s _) = s +-- | Convert to an ordered `Seq` toSeq :: Set a -> Seq a toSeq (Set _ xs) = xs +{-| Convert a `Dhall.Set.Set` to a list, preserving the original order of the+    elements+-} toList :: Set a -> [a]-toList = Data.Foldable.toList+toList (Set _ xs) = Data.Foldable.toList xs +-- | Convert a `Dhall.Set.Set` to a list of ascending elements+toAscList :: Set a -> [a]+toAscList (Set s _) = Data.Set.toAscList s++-- | Convert a list to a `Dhall.Set.Set`, remembering the element order+fromList :: Ord a => [a] -> Set a+fromList = foldl' (flip append) empty -- O(n log n) time complexity, O(n) space complexity. -- Implementing it this way is a little silly, but is faster than (nub xs). -- n.b. toList . fromList = id, only if the list elements are unique-fromList :: Ord a => [a] -> Set a-fromList = foldl' (flip append) empty --- O(log n) time complexity.+-- | Convert a @"Data.Set".`Data.Set.Set`@ to a sorted `Dhall.Set.Set`+fromSet :: Data.Set.Set a -> Set a+fromSet s = Set s (Data.Sequence.fromList (Data.Set.elems s))++-- | Append an element to the end of a `Dhall.Set.Set` append :: Ord a => a -> Set a -> Set a append x os@(Set s xs)     | Data.Set.member x s = os     | otherwise = Set (Data.Set.insert x s) (xs |> x)+-- O(log n) time complexity. +-- | The empty `Dhall.Set.Set` empty :: Set a empty = Set Data.Set.empty Data.Sequence.empty @@ -62,3 +112,36 @@ difference :: Ord a => Set a -> Set a -> [a] difference os (Set s _) =     filter (\ x -> not (Data.Set.member x s)) (toList os)++{-| Sort the set elements, forgetting their original ordering.++>>> sort (fromList [2, 1]) == fromList [1, 2]+True+-}+sort :: Ord a => Set a -> Set a+sort (Set s _) = Set s (Data.Sequence.fromList (Data.Set.toList s))++{-|+>>> isSorted (fromList [2, 1])+False+>>> isSorted (fromList [1, 2])+True+-}+isSorted :: Ord a => Set a -> Bool+isSorted s = toList s == Data.Set.toList (toSet s)++{-|+>>> null (fromList [1])+False+>>> null (fromList [])+True+-}+null :: Set a -> Bool+null (Set s _) = Data.Set.null s++{-|+>>> size (fromList [1])+1+-}+size :: Set a -> Int+size (Set s _) = Data.Set.size s
src/Dhall/Src.hs view
@@ -1,6 +1,9 @@+{-# LANGUAGE CPP                #-}+{-# LANGUAGE DeriveAnyClass     #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric      #-} {-# LANGUAGE OverloadedStrings  #-}+{-# LANGUAGE TemplateHaskell    #-}  -- | This module provides the `Src` type used for source spans in error messages @@ -9,12 +12,14 @@       Src(..)     ) where -import Data.Data (Data)-import Data.Monoid ((<>))-import Data.Text (Text)-import Data.Text.Prettyprint.Doc  (Pretty (..))-import GHC.Generics (Generic)-import Text.Megaparsec (SourcePos)+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 @@ -23,10 +28,28 @@ import qualified Text.Printf     as Printf  -- | Source code extract-data Src = Src !SourcePos !SourcePos Text-  -- Text field is intentionally lazy-  deriving (Data, Eq, Generic, Ord, Show)+data Src = Src+    { srcStart :: !SourcePos+    , srcEnd   :: !SourcePos+    , srcText  :: Text -- Text field is intentionally lazy+    } deriving (Data, Eq, Generic, Ord, Show, NFData) ++instance Lift Src where+#if MIN_VERSION_template_haskell(2,16,0)+    liftTyped (Src (SourcePos a b c) (SourcePos d e f) g) =+        [|| Src (SourcePos a (mkPos b') (mkPos c')) (SourcePos d (mkPos e') (mkPos f')) g ||]+#else+    lift (Src (SourcePos a b c) (SourcePos d e f) g) =+        [| Src (SourcePos a (mkPos b') (mkPos c')) (SourcePos d (mkPos e') (mkPos f')) g |]+#endif+      where+        b' = unPos b+        c' = unPos c+        e' = unPos e+        f' = unPos f++ instance Pretty Src where     pretty (Src begin _ text) =             pretty (Dhall.Util.snip numberedLines)@@ -55,6 +78,6 @@             inputString = Text.unpack line              outputString =-                Printf.printf ("%" <> show numberWidth <> "d: %s") n inputString+                Printf.printf ("%" <> show numberWidth <> "d│ %s") n inputString          numberedLines = Text.unlines (zipWith adapt [minimumNumber..] ls)
+ src/Dhall/Substitution.hs view
@@ -0,0 +1,34 @@+{- | This module provides types and functions used in the substitution step+     which is done before type checking and normalization.+-}++module Dhall.Substitution where++import Data.Text       (Text)+import Dhall.Normalize (subst)+import Dhall.Syntax    (Expr, Var (..))++import qualified Dhall.Map++{- | Substitutions map variables to arbitrary Dhall expressions.+     Note that we use "Dhall.Map.Map" as an underlying structure. Hence we respect insertion order.+-}+type Substitutions s a = Dhall.Map.Map Text (Expr s a)++{- | An empty substitution map.+-}+empty :: Substitutions s a+empty = Dhall.Map.empty++-- | @substitute expr s@ replaces all variables in @expr@ (or its subexpression) with their substitute.+--   For example, if the substitution map maps the variable @Foo@ to the text \"Foo\" all occurrences of @Foo@ with the text \"Foo\".+--+--   The substitutions will be done in the order they are inserted into the substitution map:+--+--   > {-# LANGUAGE OverloadedStrings #-}+--   >+--   > substitute (Dhall.Core.Var "Foo") (Dhall.Map.fromList [("Foo", Dhall.Core.Var "Bar"), ("Bar", Dhall.Core.Var "Baz")])+--+--   results in @Dhall.Core.Var \"Baz\"@ since we first substitute \"Foo\" with \"Bar\" and then the resulting \"Bar\" with the final \"Baz\".+substitute :: Expr s a -> Substitutions s a -> Expr s a+substitute expr = foldl (\memo (k, v) -> subst (V k 0) v memo) expr . Dhall.Map.toList
+ src/Dhall/Syntax.hs view
@@ -0,0 +1,31 @@+module Dhall.Syntax+    ( module Export+    ) where++import {-# SOURCE #-} Dhall.Pretty.Internal              as Export+    ( CharacterSet (..)+    )+import                Dhall.Syntax.Binding               as Export+import                Dhall.Syntax.Chunks                as Export+import                Dhall.Syntax.Const                 as Export+import                Dhall.Syntax.Expr                  as Export+import                Dhall.Syntax.FunctionBinding       as Export+import                Dhall.Syntax.Import                as Export+import                Dhall.Syntax.Instances.Applicative as Export ()+import                Dhall.Syntax.Instances.Bifunctor   as Export ()+import                Dhall.Syntax.Instances.Data        as Export ()+import                Dhall.Syntax.Instances.Eq          as Export ()+import                Dhall.Syntax.Instances.Foldable    as Export ()+import                Dhall.Syntax.Instances.Functor     as Export ()+import                Dhall.Syntax.Instances.Lift        as Export ()+import                Dhall.Syntax.Instances.Monad       as Export ()+import                Dhall.Syntax.Instances.NFData      as Export ()+import                Dhall.Syntax.Instances.Ord         as Export ()+import                Dhall.Syntax.Instances.Pretty      as Export+import                Dhall.Syntax.Instances.Show        as Export ()+import                Dhall.Syntax.Instances.Traversable as Export ()+import                Dhall.Syntax.MultiLet              as Export+import                Dhall.Syntax.Operations            as Export+import                Dhall.Syntax.RecordField           as Export+import                Dhall.Syntax.Types                 as Export+import                Dhall.Syntax.Var                   as Export
+ src/Dhall/Syntax/Binding.hs view
@@ -0,0 +1,57 @@+{-# LANGUAGE DeriveGeneric #-}++module Dhall.Syntax.Binding+    ( Binding(..)+    , makeBinding++      -- * Optics+    , bindingExprs+    ) where++import                Data.Text         (Text)+import {-# SOURCE #-} Dhall.Syntax.Expr (Expr)+import                GHC.Generics      (Generic)++-- | Record the binding part of a @let@ expression.+--+-- For example,+--+-- > let {- A -} x {- B -} : {- C -} Bool = {- D -} True in x+--+-- … will be instantiated as follows:+--+-- * @bindingSrc0@ corresponds to the @A@ comment.+-- * @variable@ is @"x"@+-- * @bindingSrc1@ corresponds to the @B@ comment.+-- * @annotation@ is 'Just' a pair, corresponding to the @C@ comment and @Bool@.+-- * @bindingSrc2@ corresponds to the @D@ comment.+-- * @value@ corresponds to @True@.+data Binding s a = Binding+    { bindingSrc0 :: Maybe s+    , variable    :: Text+    , bindingSrc1 :: Maybe s+    , annotation  :: Maybe (Maybe s, Expr s a)+    , bindingSrc2 :: Maybe s+    , value       :: Expr s a+    } deriving Generic++{-| Construct a 'Binding' with no source information and no type annotation.+-}+makeBinding :: Text -> Expr s a -> Binding s a+makeBinding name = Binding Nothing name Nothing Nothing Nothing++{-| Traverse over the immediate 'Expr' children in a 'Binding'.+-}+bindingExprs+  :: (Applicative f)+  => (Expr s a -> f (Expr s b))+  -> Binding s a -> f (Binding s b)+bindingExprs f (Binding s0 n s1 t s2 v) =+  Binding+    <$> pure s0+    <*> pure n+    <*> pure s1+    <*> traverse (traverse f) t+    <*> pure s2+    <*> f v+{-# INLINABLE bindingExprs #-}
+ src/Dhall/Syntax/Chunks.hs view
@@ -0,0 +1,141 @@+{-# LANGUAGE DeriveGeneric     #-}+{-# LANGUAGE OverloadedStrings #-}++module Dhall.Syntax.Chunks+    ( Chunks(..)++      -- * Optics+    , chunkExprs++      -- * `Data.Text.Text` manipulation+    , toDoubleQuoted+    , longestSharedWhitespacePrefix+    , linesLiteral+    , unlinesLiteral+    ) where++import                Data.List.NonEmpty (NonEmpty (..))+import                Data.String        (IsString (..))+import                Data.Text          (Text)+import                Dhall.Src          (Src)+import {-# SOURCE #-} Dhall.Syntax.Expr  (Expr)+import                GHC.Generics       (Generic)++import qualified Data.Foldable+import qualified Data.List.NonEmpty as NonEmpty+import qualified Data.Text++-- | The body of an interpolated @Text@ literal+data Chunks s a = Chunks [(Text, Expr s a)] Text+    deriving Generic++instance IsString (Chunks s a) where+    fromString str = Chunks [] (fromString str)++instance Semigroup (Chunks s a) where+    Chunks xysL zL <> Chunks         []    zR =+        Chunks xysL (zL <> zR)+    Chunks xysL zL <> Chunks ((x, y):xysR) zR =+        Chunks (xysL ++ (zL <> x, y):xysR) zR++instance Monoid (Chunks s a) where+    mempty = Chunks [] mempty++-- | A traversal over the immediate sub-expressions in 'Chunks'.+chunkExprs+  :: Applicative f+  => (Expr s a -> f (Expr t b))+  -> Chunks s a -> f (Chunks t b)+chunkExprs f (Chunks chunks final) =+  flip Chunks final <$> traverse (traverse f) chunks+{-# INLINABLE chunkExprs #-}++-- | Same as @Data.Text.splitOn@, except always returning a `NonEmpty` result+splitOn :: Text -> Text -> NonEmpty Text+splitOn needle haystack =+    case Data.Text.splitOn needle haystack of+        []     -> "" :| []+        t : ts -> t  :| ts++-- | Split `Chunks` by lines+linesLiteral :: Chunks s a -> NonEmpty (Chunks s a)+linesLiteral (Chunks [] suffix) =+    fmap (Chunks []) (splitOn "\n" suffix)+linesLiteral (Chunks ((prefix, interpolation) : pairs₀) suffix₀) =+    foldr+        NonEmpty.cons+        (Chunks ((lastLine, interpolation) : pairs₁) suffix₁ :| chunks)+        (fmap (Chunks []) initLines)+  where+    splitLines = splitOn "\n" prefix++    initLines = NonEmpty.init splitLines+    lastLine  = NonEmpty.last splitLines++    Chunks pairs₁ suffix₁ :| chunks = linesLiteral (Chunks pairs₀ suffix₀)++-- | Flatten several `Chunks` back into a single `Chunks` by inserting newlines+unlinesLiteral :: NonEmpty (Chunks s a) -> Chunks s a+unlinesLiteral chunks =+    Data.Foldable.fold (NonEmpty.intersperse "\n" chunks)++-- | Returns `True` if the `Chunks` represents a blank line+emptyLine :: Chunks s a -> Bool+emptyLine (Chunks [] ""  ) = True+emptyLine (Chunks [] "\r") = True  -- So that `\r\n` is treated as a blank line+emptyLine  _               = False++-- | Return the leading whitespace for a `Chunks` literal+leadingSpaces :: Chunks s a -> Text+leadingSpaces chunks = Data.Text.takeWhile isSpace firstText+  where+    isSpace c = c == ' ' || c == '\t'++    firstText =+        case chunks of+            Chunks                []  suffix -> suffix+            Chunks ((prefix, _) : _ ) _      -> prefix++{-| Compute the longest shared whitespace prefix for the purposes of stripping+    leading indentation+-}+longestSharedWhitespacePrefix :: NonEmpty (Chunks s a) -> Text+longestSharedWhitespacePrefix literals =+    case fmap leadingSpaces filteredLines of+        l : ls -> Data.Foldable.foldl' sharedPrefix l ls+        []     -> ""+  where+    sharedPrefix ab ac =+        case Data.Text.commonPrefixes ab ac of+            Just (a, _b, _c) -> a+            Nothing          -> ""++    -- The standard specifies to filter out blank lines for all lines *except*+    -- for the last line+    filteredLines = newInit <> pure oldLast+      where+        oldInit = NonEmpty.init literals++        oldLast = NonEmpty.last literals++        newInit = filter (not . emptyLine) oldInit++-- | Drop the first @n@ characters for a `Chunks` literal+dropLiteral :: Int -> Chunks s a -> Chunks s a+dropLiteral n (Chunks [] suffix) =+    Chunks [] (Data.Text.drop n suffix)+dropLiteral n (Chunks ((prefix, interpolation) : rest) suffix) =+    Chunks ((Data.Text.drop n prefix, interpolation) : rest) suffix++{-| Convert a single-quoted `Chunks` literal to the equivalent double-quoted+    `Chunks` literal+-}+toDoubleQuoted :: Chunks Src a -> Chunks Src a+toDoubleQuoted literal =+    unlinesLiteral (fmap (dropLiteral indent) literals)+  where+    literals = linesLiteral literal++    longestSharedPrefix = longestSharedWhitespacePrefix literals++    indent = Data.Text.length longestSharedPrefix
+ src/Dhall/Syntax/Chunks.hs-boot view
@@ -0,0 +1,8 @@+{-# LANGUAGE StandaloneKindSignatures #-}++module Dhall.Syntax.Chunks where++import Data.Kind (Type)++type Chunks :: Type -> Type -> Type+data Chunks s a
+ src/Dhall/Syntax/Const.hs view
@@ -0,0 +1,29 @@+{-# LANGUAGE DeriveGeneric #-}++module Dhall.Syntax.Const+    ( Const(..)+    ) where++import GHC.Generics (Generic)++{-| Constants for a pure type system++    The axioms are:++> ⊦ Type : Kind+> ⊦ Kind : Sort++    ... and the valid rule pairs are:++> ⊦ Type ↝ Type : Type  -- Functions from terms to terms (ordinary functions)+> ⊦ Kind ↝ Type : Type  -- Functions from types to terms (type-polymorphic functions)+> ⊦ Sort ↝ Type : Type  -- Functions from kinds to terms+> ⊦ Kind ↝ Kind : Kind  -- Functions from types to types (type-level functions)+> ⊦ Sort ↝ Kind : Sort  -- Functions from kinds to types (kind-polymorphic functions)+> ⊦ Sort ↝ Sort : Sort  -- Functions from kinds to kinds (kind-level functions)++    Note that Dhall does not support functions from terms to types and therefore+    Dhall is not a dependently typed language+-}+data Const = Type | Kind | Sort+    deriving (Bounded, Enum, Generic)
+ src/Dhall/Syntax/Expr.hs view
@@ -0,0 +1,267 @@+{-# LANGUAGE DeriveGeneric            #-}+{-# LANGUAGE StandaloneKindSignatures #-}++module Dhall.Syntax.Expr+    ( Expr(..)+    ) where++import                Data.ByteString              (ByteString)+import                Data.Kind                    (Type)+import                Data.List.NonEmpty           (NonEmpty (..))+import                Data.Sequence                (Seq)+import                Data.String                  (IsString (..))+import                Data.Text                    (Text)+import                Data.Traversable             ()+import                Dhall.Map                    (Map)+import {-# SOURCE #-} Dhall.Pretty.Internal        (CharacterSet (..))+import                Dhall.Syntax.Binding+import                Dhall.Syntax.Chunks+import                Dhall.Syntax.Const+import                Dhall.Syntax.FunctionBinding+import                Dhall.Syntax.RecordField+import                Dhall.Syntax.Types+import                Dhall.Syntax.Var+import                GHC.Generics                 (Generic)+import                Numeric.Natural              (Natural)++import qualified Data.Time as Time++{-| Syntax tree for expressions++    The @s@ type parameter is used to track the presence or absence of+    `Dhall.Src.Src` spans:++    * If @s = `Dhall.Src.Src`@ then the code may contains `Dhall.Src.Src` spans+      (either in a `Note` constructor or inline within another constructor, like+      `Let`)+    * If @s = `Data.Void.Void`@ then the code has no `Dhall.Src.Src` spans++    The @a@ type parameter is used to track the presence or absence of imports++    * If @a = `Dhall.Syntax.Import.Import`@ then the code may contain unresolved+      `Dhall.Syntax.Import.Import`s+    * If @a = `Data.Void.Void`@ then the code has no+      `Dhall.Syntax.Import.Import`s+-}+type Expr :: Type -> Type -> Type+data Expr s a+    -- | > Const c                                  ~  c+    = Const Const+    -- | > Var (V x 0)                              ~  x+    --   > Var (V x n)                              ~  x@n+    | Var Var+    -- | > Lam _ (FunctionBinding _ "x" _ _ A) b    ~  λ(x : A) -> b+    | Lam (Maybe CharacterSet) (FunctionBinding s a) (Expr s a)+    -- | > Pi _ "_" A B                               ~        A  -> B+    --   > Pi _ x   A B                               ~  ∀(x : A) -> B+    | Pi  (Maybe CharacterSet) Text (Expr s a) (Expr s a)+    -- | > App f a                                  ~  f a+    | App (Expr s a) (Expr s a)+    -- | > Let (Binding _ x _  Nothing  _ r) e      ~  let x     = r in e+    --   > Let (Binding _ x _ (Just t ) _ r) e      ~  let x : t = r in e+    --+    -- The difference between+    --+    -- > let x = a    let y = b in e+    --+    -- and+    --+    -- > let x = a in let y = b in e+    --+    -- is only an additional 'Note' around @'Let' "y" …@ in the second+    -- example.+    --+    -- See `Dhall.Syntax.MultiLet.MultiLet` for a representation of let-blocks+    -- that mirrors the source code more closely.+    | Let (Binding s a) (Expr s a)+    -- | > Annot x t                                ~  x : t+    | Annot (Expr s a) (Expr s a)+    -- | > Bool                                     ~  Bool+    | Bool+    -- | > BoolLit b                                ~  b+    | BoolLit Bool+    -- | > BoolAnd x y                              ~  x && y+    | BoolAnd (Expr s a) (Expr s a)+    -- | > BoolOr  x y                              ~  x || y+    | BoolOr  (Expr s a) (Expr s a)+    -- | > BoolEQ  x y                              ~  x == y+    | BoolEQ  (Expr s a) (Expr s a)+    -- | > BoolNE  x y                              ~  x != y+    | BoolNE  (Expr s a) (Expr s a)+    -- | > BoolIf x y z                             ~  if x then y else z+    | BoolIf (Expr s a) (Expr s a) (Expr s a)+    -- | > Bytes                                    ~ Bytes+    | Bytes+    -- | > BytesLit "\x00\xFF"                      ~ 0x"00FF"+    | BytesLit ByteString+    -- | > Natural                                  ~  Natural+    | Natural+    -- | > NaturalLit n                             ~  n+    | NaturalLit Natural+    -- | > NaturalFold                              ~  Natural/fold+    | NaturalFold+    -- | > NaturalBuild                             ~  Natural/build+    | NaturalBuild+    -- | > NaturalIsZero                            ~  Natural/isZero+    | NaturalIsZero+    -- | > NaturalEven                              ~  Natural/even+    | NaturalEven+    -- | > NaturalOdd                               ~  Natural/odd+    | NaturalOdd+    -- | > NaturalToInteger                         ~  Natural/toInteger+    | NaturalToInteger+    -- | > NaturalShow                              ~  Natural/show+    | NaturalShow+    -- | > NaturalSubtract                          ~  Natural/subtract+    | NaturalSubtract+    -- | > NaturalPlus x y                          ~  x + y+    | NaturalPlus (Expr s a) (Expr s a)+    -- | > NaturalTimes x y                         ~  x * y+    | NaturalTimes (Expr s a) (Expr s a)+    -- | > Integer                                  ~  Integer+    | Integer+    -- | > IntegerLit n                             ~  ±n+    | IntegerLit Integer+    -- | > IntegerClamp                             ~  Integer/clamp+    | IntegerClamp+    -- | > IntegerNegate                            ~  Integer/negate+    | IntegerNegate+    -- | > IntegerShow                              ~  Integer/show+    | IntegerShow+    -- | > IntegerToDouble                          ~  Integer/toDouble+    | IntegerToDouble+    -- | > Double                                   ~  Double+    | Double+    -- | > DoubleLit n                              ~  n+    | DoubleLit DhallDouble+    -- | > DoubleShow                               ~  Double/show+    | DoubleShow+    -- | > Text                                     ~  Text+    | Text+    -- | > TextLit (Chunks [(t1, e1), (t2, e2)] t3) ~  "t1${e1}t2${e2}t3"+    | TextLit (Chunks s a)+    -- | > TextAppend x y                           ~  x ++ y+    | TextAppend (Expr s a) (Expr s a)+    -- | > TextReplace                              ~ Text/replace+    | TextReplace+    -- | > TextShow                                 ~  Text/show+    | TextShow+    -- | > Date                                     ~  Date+    | Date+    -- | > DateLiteral (fromGregorian _YYYY _MM _DD) ~ YYYY-MM-DD+    | DateLiteral Time.Day+    -- | > DateShow                                 ~  Date/show+    | DateShow+    -- | > Time                                     ~  Time+    | Time+    -- | > TimeLiteral (TimeOfDay hh mm ss) _       ~  hh:mm:ss+    | TimeLiteral+        Time.TimeOfDay+        Word+        -- ^ Precision+    -- | > TimeShow                                 ~  Time/show+    | TimeShow+    -- | > TimeZone                                 ~  TimeZone+    | TimeZone+    -- | > TimeZoneLiteral (TimeZone ( 60 * _HH + _MM) _ _) ~ +HH:MM+    -- | > TimeZoneLiteral (TimeZone (-60 * _HH + _MM) _ _) ~ -HH:MM+    | TimeZoneLiteral Time.TimeZone+    -- | > TimeZoneShow                             ~  TimeZone/Show+    | TimeZoneShow+    -- | > List                                     ~  List+    | List+    -- | > ListLit (Just t ) []                     ~  [] : t+    --   > ListLit  Nothing  [x, y, z]              ~  [x, y, z]+    --+    --   Invariant: A non-empty list literal is always represented as+    --   @ListLit Nothing xs@.+    --+    --   When an annotated, non-empty list literal is parsed, it is represented+    --   as+    --+    --   > Annot (ListLit Nothing [x, y, z]) t      ~ [x, y, z] : t++    -- Eventually we should have separate constructors for empty and non-empty+    -- list literals. For now it's easier to check the invariant in @infer@.+    -- See https://github.com/dhall-lang/dhall-haskell/issues/1359#issuecomment-537087234.+    | ListLit (Maybe (Expr s a)) (Seq (Expr s a))+    -- | > ListAppend x y                           ~  x # y+    | ListAppend (Expr s a) (Expr s a)+    -- | > ListBuild                                ~  List/build+    | ListBuild+    -- | > ListFold                                 ~  List/fold+    | ListFold+    -- | > ListLength                               ~  List/length+    | ListLength+    -- | > ListHead                                 ~  List/head+    | ListHead+    -- | > ListLast                                 ~  List/last+    | ListLast+    -- | > ListIndexed                              ~  List/indexed+    | ListIndexed+    -- | > ListReverse                              ~  List/reverse+    | ListReverse+    -- | > Optional                                 ~  Optional+    | Optional+    -- | > Some e                                   ~  Some e+    | Some (Expr s a)+    -- | > None                                     ~  None+    | None+    -- | > Record [ (k1, RecordField _ t1)          ~  { k1 : t1, k2 : t1 }+    --   >        , (k2, RecordField _ t2)+    --   >        ]+    | Record    (Map Text (RecordField s a))+    -- | > RecordLit [ (k1, RecordField _ v1)       ~  { k1 = v1, k2 = v2 }+    --   >           , (k2, RecordField _ v2)+    --   >           ]+    | RecordLit (Map Text (RecordField s a))+    -- | > Union        [(k1, Just t1), (k2, Nothing)] ~  < k1 : t1 | k2 >+    | Union     (Map Text (Maybe (Expr s a)))+    -- | > Combine _ Nothing x y                    ~  x ∧ y+    --+    -- The first field is a `Just` when the `Combine` operator is introduced+    -- as a result of desugaring duplicate record fields:+    --+    --   > RecordLit [ ( k                          ~ { k = x, k = y }+    --   >           , RecordField+    --   >              _+    --   >              (Combine (Just k) x y)+    --   >            )]+    | Combine (Maybe CharacterSet) (Maybe Text) (Expr s a) (Expr s a)+    -- | > CombineTypes _ x y                       ~  x ⩓ y+    | CombineTypes (Maybe CharacterSet) (Expr s a) (Expr s a)+    -- | > Prefer _ _ x y                           ~  x ⫽ y+    | Prefer (Maybe CharacterSet) PreferAnnotation (Expr s a) (Expr s a)+    -- | > RecordCompletion x y                     ~  x::y+    | RecordCompletion (Expr s a) (Expr s a)+    -- | > Merge x y (Just t )                      ~  merge x y : t+    --   > Merge x y  Nothing                       ~  merge x y+    | Merge (Expr s a) (Expr s a) (Maybe (Expr s a))+    -- | > ToMap x (Just t)                         ~  toMap x : t+    --   > ToMap x  Nothing                         ~  toMap x+    | ToMap (Expr s a) (Maybe (Expr s a))+    -- | > ShowConstructor x                        ~  showConstructor x+    | ShowConstructor (Expr s a)+    -- | > Field e (FieldSelection _ x _)              ~  e.x+    | Field (Expr s a) (FieldSelection s)+    -- | > Project e (Left xs)                      ~  e.{ xs }+    --   > Project e (Right t)                      ~  e.(t)+    | Project (Expr s a) (Either [Text] (Expr s a))+    -- | > Assert e                                 ~  assert : e+    | Assert (Expr s a)+    -- | > Equivalent _ x y                           ~  x ≡ y+    | Equivalent (Maybe CharacterSet) (Expr s a) (Expr s a)+    -- | > With x y e                               ~  x with y = e+    | With (Expr s a) (NonEmpty WithComponent) (Expr s a)+    -- | > Note s x                                 ~  e+    | Note s (Expr s a)+    -- | > ImportAlt                                ~  e1 ? e2+    | ImportAlt (Expr s a) (Expr s a)+    -- | > Embed import                             ~  import+    | Embed a+    deriving (Generic)+-- NB: If you add a constructor to Expr, please also update the Arbitrary+-- instance in Dhall.Test.QuickCheck.++instance IsString (Expr s a) where+    fromString str = Var (fromString str)
+ src/Dhall/Syntax/Expr.hs-boot view
@@ -0,0 +1,8 @@+{-# LANGUAGE StandaloneKindSignatures #-}++module Dhall.Syntax.Expr where++import Data.Kind (Type)++type Expr :: Type -> Type -> Type+data Expr s a
+ src/Dhall/Syntax/FunctionBinding.hs view
@@ -0,0 +1,53 @@+{-# LANGUAGE DeriveGeneric #-}++module Dhall.Syntax.FunctionBinding+    ( FunctionBinding(..)+    , makeFunctionBinding++      -- * Optics+    , functionBindingExprs+    ) where++import                Data.Text         (Text)+import {-# SOURCE #-} Dhall.Syntax.Expr (Expr)+import                GHC.Generics      (Generic)++-- | Record the label of a function or a function-type expression+--+-- For example,+--+-- > λ({- A -} a {- B -} : {- C -} T) -> e+--+-- … will be instantiated as follows:+--+-- * @functionBindingSrc0@ corresponds to the @A@ comment+-- * @functionBindingVariable@ is @a@+-- * @functionBindingSrc1@ corresponds to the @B@ comment+-- * @functionBindingSrc2@ corresponds to the @C@ comment+-- * @functionBindingAnnotation@ is @T@+data FunctionBinding s a = FunctionBinding+    { functionBindingSrc0 :: Maybe s+    , functionBindingVariable :: Text+    , functionBindingSrc1 :: Maybe s+    , functionBindingSrc2 :: Maybe s+    , functionBindingAnnotation :: Expr s a+    } deriving Generic++-- | Smart constructor for 'FunctionBinding' with no src information+makeFunctionBinding :: Text -> Expr s a -> FunctionBinding s a+makeFunctionBinding l t = FunctionBinding Nothing l Nothing Nothing t++{-| Traverse over the immediate 'Expr' children in a 'FunctionBinding'.+-}+functionBindingExprs+    :: Applicative f+    => (Expr s a -> f (Expr s b))+    -> FunctionBinding s a -> f (FunctionBinding s b)+functionBindingExprs f (FunctionBinding s0 label s1 s2 type_) =+    FunctionBinding+        <$> pure s0+        <*> pure label+        <*> pure s1+        <*> pure s2+        <*> f type_+{-# INLINABLE functionBindingExprs #-}
+ src/Dhall/Syntax/Import.hs view
@@ -0,0 +1,139 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric      #-}+{-# LANGUAGE OverloadedStrings  #-}+{-# LANGUAGE RecordWildCards    #-}++module Dhall.Syntax.Import+    ( Directory(..)+    , File(..)+    , FilePrefix(..)+    , Import(..)+    , ImportHashed(..)+    , ImportMode(..)+    , ImportType(..)+    , URL(..)+    , Scheme(..)+    ) where++import Data.Data                      (Data)+import Data.Text                      (Text)+import Dhall.Src                      (Src (..))+import Dhall.Syntax.Expr              (Expr (..))+import Dhall.Syntax.Instances.Data    ()+import Dhall.Syntax.Instances.Functor ()+import GHC.Generics                   (Generic)++import qualified Dhall.Crypto++{-| Internal representation of a directory that stores the path components in+    reverse order++    In other words, the directory @\/foo\/bar\/baz@ is encoded as+    @Directory { components = [ "baz", "bar", "foo" ] }@+-}+newtype Directory = Directory { components :: [Text] }+    deriving (Data, Generic)++{-| A `File` is a `directory` followed by one additional path component+    representing the `file` name+-}+data File = File+    { directory :: Directory+    , file      :: Text+    } deriving (Data, Generic)++-- | The beginning of a file path which anchors subsequent path components+data FilePrefix+    = Absolute+    -- ^ Absolute path+    | Here+    -- ^ Path relative to @.@+    | Parent+    -- ^ Path relative to @..@+    | Home+    -- ^ Path relative to @~@+    deriving (Data, Generic)++-- | The URI scheme+data Scheme = HTTP | HTTPS+    deriving (Data, Generic)++-- | This type stores all of the components of a remote import+data URL = URL+    { scheme    :: Scheme+    , authority :: Text+    , path      :: File+    , query     :: Maybe Text+    , headers   :: Maybe (Expr Src Import)+    } deriving (Data, Generic)++-- | The type of import (i.e. local vs. remote vs. environment)+data ImportType+    = Local FilePrefix File+    -- ^ Local path+    | Remote URL+    -- ^ URL of remote resource and optional headers stored in an import+    | Env  Text+    -- ^ Environment variable+    | Missing+    deriving (Data, Generic)++-- | How to interpret the import's contents (i.e. as Dhall code or raw text)+data ImportMode = Code | RawText | Location | RawBytes+  deriving (Data, Generic)++-- | A `ImportType` extended with an optional hash for semantic integrity checks+data ImportHashed = ImportHashed+    { hash       :: Maybe Dhall.Crypto.SHA256Digest+    , importType :: ImportType+    } deriving (Data, Generic)++-- | Reference to an external resource+data Import = Import+    { importHashed :: ImportHashed+    , importMode   :: ImportMode+    } deriving (Data, Generic)+++++instance Semigroup Directory where+    Directory components0 <> Directory components1 =+        Directory (components1 <> components0)++instance Semigroup File where+    File directory0 _ <> File directory1 file =+        File (directory0 <> directory1) file++instance Semigroup ImportType where+    Local prefix file0 <> Local Here file1 = Local prefix (file0 <> file1)++    Remote (URL { path = path0, ..}) <> Local Here path1 =+        Remote (URL { path = path0 <> path1, ..})++    Local prefix file0 <> Local Parent file1 =+        Local prefix (file0 <> parent <> file1)++    Remote (URL { path = path0, .. }) <> Local Parent path1 =+        Remote (URL { path = path0 <> parent <> path1, .. })++    import0 <> Remote (URL { headers = headers0, .. }) =+        Remote (URL { headers = headers1, .. })+      where+        importHashed0 = Import (ImportHashed Nothing import0) Code++        headers1 = fmap (fmap (importHashed0 <>)) headers0++    _ <> import1 =+        import1++instance Semigroup ImportHashed where+    ImportHashed _ importType0 <> ImportHashed hash importType1 =+        ImportHashed hash (importType0 <> importType1)++instance Semigroup Import where+    Import importHashed0 _ <> Import importHashed1 code =+        Import (importHashed0 <> importHashed1) code++parent :: File+parent = File { directory = Directory { components = [ ".." ] }, file = "" }
+ src/Dhall/Syntax/Instances/Applicative.hs view
@@ -0,0 +1,36 @@+{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Applicative () where++import Dhall.Syntax.Binding+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.Instances.Functor ()+import Dhall.Syntax.Operations+import Dhall.Syntax.RecordField++import qualified Lens.Micro as Lens++instance Applicative (Expr s) where+    pure = Embed++    expression <*> k = case expression of+        Embed a     -> a <$> k+        Let a b     -> Let (adaptBinding a) (b <*> k)+        Note a b    -> Note a (b <*> k)+        Record a    -> Record $ adaptRecordField <$> a+        RecordLit a -> RecordLit $ adaptRecordField <$> a+        Lam cs a b  -> Lam cs (adaptFunctionBinding a) (b <*> k)+        Field a b   -> Field (a <*> k) b+        _ -> Lens.over unsafeSubExpressions (<*> k) expression+      where+        adaptRecordField (RecordField s0 e s1 s2) =+            RecordField s0 (e <*> k) s1 s2++        adaptBinding (Binding src0 c src1 d src2 e) =+            Binding src0 c src1 (fmap adaptBindingAnnotation d) src2 (e <*> k)++        adaptFunctionBinding (FunctionBinding src0 label src1 src2 type_) =+            FunctionBinding src0 label src1 src2 (type_ <*> k)++        adaptBindingAnnotation (src3, f) = (src3, f <*> k)
+ src/Dhall/Syntax/Instances/Bifunctor.hs view
@@ -0,0 +1,44 @@+{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Bifunctor () where++import Data.Bifunctor                 (Bifunctor (..))+import Dhall.Syntax.Binding+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.Instances.Functor ()+import Dhall.Syntax.Operations+import Dhall.Syntax.RecordField++import qualified Lens.Micro as Lens++instance Bifunctor Binding where+    first k (Binding src0 a src1 b src2 c) =+        Binding (fmap k src0) a (fmap k src1) (fmap adapt0 b) (fmap k src2) (first k c)+      where+        adapt0 (src3, d) = (fmap k src3, first k d)++    second = fmap++instance Bifunctor RecordField where+    first k (RecordField s0 value' s1 s2) =+        RecordField (k <$> s0) (first k value') (k <$> s1) (k <$> s2)+    second = fmap++instance Bifunctor FunctionBinding where+    first k (FunctionBinding src0 label src1 src2 type_) =+        FunctionBinding (k <$> src0) label (k <$> src1) (k <$> src2) (first k type_)++    second = fmap++instance Bifunctor Expr where+    first k (Note a b   ) = Note (k a) (first k b)+    first _ (Embed a    ) = Embed a+    first k (Let a b    ) = Let (first k a) (first k b)+    first k (Record a   ) = Record $ first k <$> a+    first k (RecordLit a) = RecordLit $ first k <$> a+    first k (Lam cs a b ) = Lam cs (first k a) (first k b)+    first k (Field a b  ) = Field (first k a) (k <$> b)+    first k  expression  = Lens.over unsafeSubExpressions (first k) expression++    second = fmap
+ src/Dhall/Syntax/Instances/Data.hs view
@@ -0,0 +1,28 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE StandaloneDeriving #-}++{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Data () where++import Data.Data                    (Data)+import Dhall.Syntax.Binding+import Dhall.Syntax.Chunks+import Dhall.Syntax.Const+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.RecordField+import Dhall.Syntax.Types+import Dhall.Syntax.Var++deriving instance Data Const+deriving instance Data Var+deriving instance (Data a, Data s) => Data (Binding s a)+deriving instance Data DhallDouble+deriving instance (Data a, Data s) => Data (Chunks s a)+deriving instance Data PreferAnnotation+deriving instance (Data a, Data s) => Data (RecordField s a)+deriving instance (Data a, Data s) => Data (FunctionBinding s a)+deriving instance Data s => Data (FieldSelection s)+deriving instance Data WithComponent+deriving instance (Data a, Data s) => Data (Expr s a)
+ src/Dhall/Syntax/Instances/Eq.hs view
@@ -0,0 +1,67 @@+{-# LANGUAGE StandaloneDeriving #-}++{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Eq () where++import Data.Bits                    (xor)+import Dhall.Syntax.Binding+import Dhall.Syntax.Chunks+import Dhall.Syntax.Const+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.Import+import Dhall.Syntax.RecordField+import Dhall.Syntax.Types+import Dhall.Syntax.Var++-- $setup+-- >>> import Data.Void (Void)+-- >>> import Dhall.Binary () -- For the orphan instance for `Serialise (Expr Void Import)`++deriving instance Eq Const+deriving instance Eq Var+deriving instance (Eq s, Eq a) => Eq (Binding s a)+deriving instance (Eq s, Eq a) => Eq (Chunks s a)+deriving instance Eq PreferAnnotation+deriving instance (Eq s, Eq a) => Eq (RecordField s a)+deriving instance (Eq s, Eq a) => Eq (FunctionBinding s a)+deriving instance Eq s => Eq (FieldSelection s)+deriving instance Eq WithComponent+-- | This instance encodes what the Dhall standard calls an \"exact match\"+-- between two expressions.+--+-- Note that+--+-- >>> nan = DhallDouble (0/0)+-- >>> DoubleLit nan == DoubleLit nan+-- True+deriving instance (Eq s, Eq a) => Eq (Expr s a)+deriving instance Eq Directory+deriving instance Eq File+deriving instance Eq FilePrefix+deriving instance Eq Scheme+deriving instance Eq URL+deriving instance Eq ImportType+deriving instance Eq ImportMode+deriving instance Eq ImportHashed+deriving instance Eq Import++-- | This instance satisfies all the customary 'Eq' laws except substitutivity.+--+-- In particular:+--+-- >>> nan = DhallDouble (0/0)+-- >>> nan == nan+-- True+--+-- This instance is also consistent with with the binary encoding of Dhall @Double@s:+--+-- >>> toBytes n = Dhall.Binary.encodeExpression (DoubleLit n :: Expr Void Import)+--+-- prop> \a b -> (a == b) == (toBytes a == toBytes b)+instance Eq DhallDouble where+    DhallDouble a == DhallDouble b+        | isNaN a && isNaN b                      = True+        | isNegativeZero a `xor` isNegativeZero b = False+        | otherwise                               = a == b
+ src/Dhall/Syntax/Instances/Foldable.hs view
@@ -0,0 +1,20 @@+{-# LANGUAGE DeriveFoldable     #-}+{-# LANGUAGE StandaloneDeriving #-}++{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Foldable () where++import Dhall.Syntax.Binding+import Dhall.Syntax.Chunks+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.RecordField+import Dhall.Syntax.Types++deriving instance Foldable (Binding s)+deriving instance Foldable (Chunks s)+deriving instance Foldable (RecordField s)+deriving instance Foldable (FunctionBinding s)+deriving instance Foldable FieldSelection+deriving instance Foldable (Expr s)
+ src/Dhall/Syntax/Instances/Functor.hs view
@@ -0,0 +1,37 @@+{-# LANGUAGE DeriveFunctor      #-}+{-# LANGUAGE StandaloneDeriving #-}++{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Functor () where++import                Dhall.Syntax.Binding+import                Dhall.Syntax.Chunks+import                Dhall.Syntax.Expr+import                Dhall.Syntax.FunctionBinding+import {-# SOURCE #-} Dhall.Syntax.Operations      (unsafeSubExpressions)+import                Dhall.Syntax.RecordField+import                Dhall.Syntax.Types++import qualified Lens.Micro as Lens++deriving instance Functor (Binding s)+deriving instance Functor (Chunks s)+deriving instance Functor (RecordField s)+deriving instance Functor (FunctionBinding s)+deriving instance Functor FieldSelection++-- This instance is hand-written due to the fact that deriving+-- it does not give us an INLINABLE pragma. We annotate this fmap+-- implementation with this pragma below to allow GHC to, possibly,+-- inline the implementation for performance improvements.+instance Functor (Expr s) where+  fmap f (Embed a) = Embed (f a)+  fmap f (Let b e2) = Let (fmap f b) (fmap f e2)+  fmap f (Note s e1) = Note s (fmap f e1)+  fmap f (Record a) = Record $ fmap f <$> a+  fmap f (RecordLit a) = RecordLit $ fmap f <$> a+  fmap f (Lam cs fb e) = Lam cs (f <$> fb) (f <$> e)+  fmap f (Field a b) = Field (f <$> a) b+  fmap f expression = Lens.over unsafeSubExpressions (fmap f) expression+  {-# INLINABLE fmap #-}
+ src/Dhall/Syntax/Instances/Lift.hs view
@@ -0,0 +1,42 @@+{-# LANGUAGE CPP                #-}+{-# LANGUAGE DeriveLift         #-}+{-# LANGUAGE StandaloneDeriving #-}++{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Lift () where++import Dhall.Syntax.Binding+import Dhall.Syntax.Chunks+import Dhall.Syntax.Const+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.RecordField+import Dhall.Syntax.Types+import Dhall.Syntax.Var+import Language.Haskell.TH.Syntax   (Lift)++#if !MIN_VERSION_template_haskell(2,21,0)+import qualified Data.Fixed as Fixed+#endif+import qualified Data.Time as Time++#if !MIN_VERSION_time(1,14,0)+deriving instance Lift Time.Day+#endif+deriving instance Lift Time.TimeOfDay+deriving instance Lift Time.TimeZone+#if !MIN_VERSION_template_haskell(2,21,0)+deriving instance Lift (Fixed.Fixed a)+#endif+deriving instance Lift Const+deriving instance Lift Var+deriving instance (Lift s, Lift a) => Lift (Binding s a)+deriving instance Lift DhallDouble+deriving instance (Lift s, Lift a) => Lift (Chunks s a)+deriving instance Lift PreferAnnotation+deriving instance (Lift s, Lift a) => Lift (RecordField s a)+deriving instance (Lift s, Lift a) => Lift (FunctionBinding s a)+deriving instance Lift s => Lift (FieldSelection s)+deriving instance Lift WithComponent+deriving instance (Lift s, Lift a) => Lift (Expr s a)
+ src/Dhall/Syntax/Instances/Monad.hs view
@@ -0,0 +1,36 @@+{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Monad () where++import Dhall.Syntax.Binding+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.Instances.Applicative ()+import Dhall.Syntax.Operations+import Dhall.Syntax.RecordField++import qualified Lens.Micro as Lens++instance Monad (Expr s) where+    return = pure++    expression >>= k = case expression of+        Embed a     -> k a+        Let a b     -> Let (adaptBinding a) (b >>= k)+        Note a b    -> Note a (b >>= k)+        Record a    -> Record $ bindRecordKeyValues <$> a+        RecordLit a -> RecordLit $ bindRecordKeyValues <$> a+        Lam cs a b  -> Lam cs (adaptFunctionBinding a) (b >>= k)+        Field a b   -> Field (a >>= k) b+        _ -> Lens.over unsafeSubExpressions (>>= k) expression+      where+        bindRecordKeyValues (RecordField s0 e s1 s2) =+            RecordField s0 (e >>= k) s1 s2++        adaptBinding (Binding src0 c src1 d src2 e) =+            Binding src0 c src1 (fmap adaptBindingAnnotation d) src2 (e >>= k)++        adaptFunctionBinding (FunctionBinding src0 label src1 src2 type_) =+            FunctionBinding src0 label src1 src2 (type_ >>= k)++        adaptBindingAnnotation (src3, f) = (src3, f >>= k)
+ src/Dhall/Syntax/Instances/NFData.hs view
@@ -0,0 +1,35 @@+{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.NFData () where++import Control.DeepSeq              (NFData)+import Dhall.Syntax.Binding+import Dhall.Syntax.Chunks+import Dhall.Syntax.Const+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.Import+import Dhall.Syntax.RecordField+import Dhall.Syntax.Types+import Dhall.Syntax.Var++instance NFData Const+instance NFData Var+instance (NFData s, NFData a) => NFData (Binding s a)+instance NFData DhallDouble+instance (NFData s, NFData a) => NFData (Chunks s a)+instance NFData PreferAnnotation+instance (NFData s, NFData a) => NFData (RecordField s a)+instance (NFData s, NFData a) => NFData (FunctionBinding s a)+instance NFData s => NFData (FieldSelection s)+instance NFData WithComponent+instance (NFData s, NFData a) => NFData (Expr s a)+instance NFData Directory+instance NFData File+instance NFData FilePrefix+instance NFData Scheme+instance NFData URL+instance NFData ImportType+instance NFData ImportMode+instance NFData ImportHashed+instance NFData Import
+ src/Dhall/Syntax/Instances/Ord.hs view
@@ -0,0 +1,45 @@+{-# LANGUAGE StandaloneDeriving #-}++{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Ord () where++import Dhall.Syntax.Binding+import Dhall.Syntax.Chunks+import Dhall.Syntax.Const+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.Import+import Dhall.Syntax.Instances.Eq    ()+import Dhall.Syntax.RecordField+import Dhall.Syntax.Types+import Dhall.Syntax.Var++deriving instance Ord Const+deriving instance Ord Var+deriving instance (Ord s, Ord a) => Ord (Binding s a)+deriving instance (Ord s, Ord a) => Ord (Chunks s a)+deriving instance Ord PreferAnnotation+deriving instance (Ord s, Ord a) => Ord (RecordField s a)+deriving instance (Ord s, Ord a) => Ord (FunctionBinding s a)+deriving instance Ord s => Ord (FieldSelection s)+deriving instance Ord WithComponent+-- | Note that this 'Ord' instance inherits `DhallDouble`'s defects.+deriving instance (Ord s, Ord a) => Ord (Expr s a)+deriving instance Ord Directory+deriving instance Ord File+deriving instance Ord FilePrefix+deriving instance Ord Scheme+deriving instance Ord URL+deriving instance Ord ImportType+deriving instance Ord ImportMode+deriving instance Ord ImportHashed+deriving instance Ord Import++-- | This instance relies on the 'Eq' instance for 'DhallDouble' but cannot+-- satisfy the customary 'Ord' laws when @NaN@ is involved.+instance Ord DhallDouble where+    compare a@(DhallDouble a') b@(DhallDouble b') =+        if a == b+            then EQ+            else compare a' b'
+ src/Dhall/Syntax/Instances/Pretty.hs view
@@ -0,0 +1,135 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards   #-}++{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Pretty+    ( pathCharacter+    ) where++import                Data.Text             (Text)+import {-# SOURCE #-} Dhall.Pretty.Internal+import                Dhall.Syntax.Const+import                Dhall.Syntax.Expr+import                Dhall.Syntax.Import+import                Dhall.Syntax.Var+import                Prettyprinter         (Doc, Pretty)++import qualified Data.Text+import qualified Network.URI   as URI+import qualified Prettyprinter as Pretty++instance Pretty Const where+    pretty = Pretty.unAnnotate . prettyConst++instance Pretty Var where+    pretty = Pretty.unAnnotate . prettyVar++-- | Generates a syntactically valid Dhall program+instance Pretty a => Pretty (Expr s a) where+    pretty = Pretty.unAnnotate . prettyExpr++instance Pretty Directory where+    pretty (Directory {..}) = foldMap prettyPathComponent (reverse components)++prettyPathComponent :: Text -> Doc ann+prettyPathComponent text+    | Data.Text.all pathCharacter text =+        "/" <> Pretty.pretty text+    | otherwise =+        "/\"" <> Pretty.pretty text <> "\""++instance Pretty File where+    pretty (File {..}) =+            Pretty.pretty directory+        <>  prettyPathComponent file++instance Pretty FilePrefix where+    pretty Absolute = ""+    pretty Here     = "."+    pretty Parent   = ".."+    pretty Home     = "~"++instance Pretty URL where+    pretty (URL {..}) =+            schemeDoc+        <>  "://"+        <>  Pretty.pretty authority+        <>  pathDoc+        <>  queryDoc+        <>  foldMap prettyHeaders headers+      where+        prettyHeaders h =+          " using (" <> Pretty.unAnnotate (Pretty.pretty h) <> ")"++        File {..} = path++        Directory {..} = directory++        pathDoc =+                foldMap prettyURIComponent (reverse components)+            <>  prettyURIComponent file++        schemeDoc = case scheme of+            HTTP  -> "http"+            HTTPS -> "https"++        queryDoc = case query of+            Nothing -> ""+            Just q  -> "?" <> Pretty.pretty q++prettyURIComponent :: Text -> Doc ann+prettyURIComponent text =+        Pretty.pretty $ URI.normalizeCase $ URI.normalizeEscape $ "/" <> Data.Text.unpack text++instance Pretty ImportType where+    pretty (Local prefix file) =+        Pretty.pretty prefix <> Pretty.pretty file++    pretty (Remote url) = Pretty.pretty url++    pretty (Env env) = "env:" <> prettyEnvironmentVariable env++    pretty Missing = "missing"++instance Pretty ImportHashed where+    pretty (ImportHashed  Nothing p) =+      Pretty.pretty p+    pretty (ImportHashed (Just h) p) =+      Pretty.group (Pretty.flatAlt long short)+      where+        long =+            Pretty.align+                (   Pretty.pretty p <> Pretty.hardline+                <>  "  sha256:" <> Pretty.pretty (show h)+                )++        short = Pretty.pretty p <> " sha256:" <> Pretty.pretty (show h)++instance Pretty Import where+    pretty (Import {..}) = Pretty.pretty importHashed <> Pretty.pretty suffix+      where+        suffix :: Text+        suffix = case importMode of+            RawText  -> " as Text"+            Location -> " as Location"+            Code     -> ""+            RawBytes -> " as Bytes"++{-| Returns `True` if the given `Char` is valid within an unquoted path+    component++    This is exported for reuse within the @"Dhall.Parser.Token"@ module+-}+pathCharacter :: Char -> Bool+pathCharacter c =+         '\x21' == c+    ||  ('\x24' <= c && c <= '\x27')+    ||  ('\x2A' <= c && c <= '\x2B')+    ||  ('\x2D' <= c && c <= '\x2E')+    ||  ('\x30' <= c && c <= '\x3B')+    ||  c == '\x3D'+    ||  ('\x40' <= c && c <= '\x5A')+    ||  ('\x5E' <= c && c <= '\x7A')+    ||  c == '\x7C'+    ||  c == '\x7E'
+ src/Dhall/Syntax/Instances/Pretty.hs-boot view
@@ -0,0 +1,8 @@+{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Pretty where++import Dhall.Syntax.Expr (Expr)+import Prettyprinter     (Pretty)++instance Pretty a => Pretty (Expr s a)
+ src/Dhall/Syntax/Instances/Show.hs view
@@ -0,0 +1,36 @@+{-# LANGUAGE StandaloneDeriving #-}++{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Show () where++import Dhall.Syntax.Binding+import Dhall.Syntax.Chunks+import Dhall.Syntax.Const+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.Import+import Dhall.Syntax.RecordField+import Dhall.Syntax.Types+import Dhall.Syntax.Var++deriving instance Show Const+deriving instance Show Var+deriving instance (Show s, Show a) => Show (Binding s a)+deriving instance Show DhallDouble+deriving instance (Show s, Show a) => Show (Chunks s a)+deriving instance Show PreferAnnotation+deriving instance (Show s, Show a) => Show (RecordField s a)+deriving instance (Show s, Show a) => Show (FunctionBinding s a)+deriving instance Show s => Show (FieldSelection s)+deriving instance Show WithComponent+deriving instance (Show s, Show a) => Show (Expr s a)+deriving instance Show Directory+deriving instance Show File+deriving instance Show FilePrefix+deriving instance Show Scheme+deriving instance Show URL+deriving instance Show ImportType+deriving instance Show ImportMode+deriving instance Show ImportHashed+deriving instance Show Import
+ src/Dhall/Syntax/Instances/Traversable.hs view
@@ -0,0 +1,22 @@+{-# LANGUAGE DeriveTraversable  #-}+{-# LANGUAGE StandaloneDeriving #-}++{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Traversable () where++import Dhall.Syntax.Binding+import Dhall.Syntax.Chunks+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.Instances.Foldable ()+import Dhall.Syntax.Instances.Functor  ()+import Dhall.Syntax.RecordField+import Dhall.Syntax.Types++deriving instance Traversable (Binding s)+deriving instance Traversable (Chunks s)+deriving instance Traversable (RecordField s)+deriving instance Traversable (FunctionBinding s)+deriving instance Traversable FieldSelection+deriving instance Traversable (Expr s)
+ src/Dhall/Syntax/MultiLet.hs view
@@ -0,0 +1,62 @@+{-# LANGUAGE LambdaCase #-}++{- | Instead of converting explicitly between 'Expr's and 'MultiLet', it might+be nicer to use a pattern synonym:++> pattern MultiLet' :: NonEmpty (Binding s a) -> Expr s a -> Expr s a+> pattern MultiLet' as b <- (multiLetFromExpr -> Just (MultiLet as b)) where+>   MultiLet' as b = wrapInLets as b+>+> multiLetFromExpr :: Expr s a -> Maybe (MultiLet s a)+> multiLetFromExpr = \case+>     Let x mA a b -> Just (multiLet x mA a b)+>     _ -> Nothing++This works in principle, but GHC as of v8.8.1 doesn't handle it well:+https://gitlab.haskell.org/ghc/ghc/issues/17096++This should be fixed by GHC-8.10, so it might be worth revisiting then.+-}++module Dhall.Syntax.MultiLet+    ( MultiLet(..)+    , multiLet+    , wrapInLets+    ) where++import Data.List.NonEmpty   (NonEmpty (..))+import Dhall.Syntax.Binding (Binding)+import Dhall.Syntax.Expr    (Expr (..))++import qualified Data.List.NonEmpty as NonEmpty++{-| Generate a 'MultiLet' from the contents of a 'Let'.++    In the resulting @'MultiLet' bs e@, @e@ is guaranteed not to be a 'Let',+    but it might be a @('Note' … ('Let' …))@.++    Given parser output, 'multiLet' consolidates @let@s that formed a+    let-block in the original source.+-}+multiLet :: Binding s a -> Expr s a -> MultiLet s a+multiLet b0 = \case+    Let b1 e1 ->+        let MultiLet bs e = multiLet b1 e1+        in  MultiLet (NonEmpty.cons b0 bs) e+    e -> MultiLet (b0 :| []) e++{-| Wrap let-'Binding's around an 'Expr'.++'wrapInLets' can be understood as an inverse for 'multiLet':++> let MultiLet bs e1 = multiLet b e0+>+> wrapInLets bs e1 == Let b e0+-}+wrapInLets :: Foldable f => f (Binding s a) -> Expr s a -> Expr s a+wrapInLets bs e = foldr Let e bs++{-| This type represents 1 or more nested `Let` bindings that have been+    coalesced together for ease of manipulation+-}+data MultiLet s a = MultiLet (NonEmpty (Binding s a)) (Expr s a)
+ src/Dhall/Syntax/Operations.hs view
@@ -0,0 +1,394 @@+{-# LANGUAGE LambdaCase        #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes        #-}++module Dhall.Syntax.Operations+    ( -- * Optics+      subExpressions+    , subExpressionsWith+    , unsafeSubExpressions++      -- * Handling 'Note's+    , denote+    , renote+    , shallowDenote++      -- * Reserved identifiers+    , reservedIdentifiers+    , reservedKeywords++      -- * Utilities+    , internalError+      -- `shift` should really be in `Dhall.Normalize`, but it's here to avoid a+      -- module cycle+    , shift+    ) where++import Data.HashSet                 (HashSet)+import Data.Text                    (Text)+import Data.Void                    (Void)+import Dhall.Syntax.Binding         (Binding (..), bindingExprs)+import Dhall.Syntax.Chunks          (chunkExprs)+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.RecordField     (RecordField (..), recordFieldExprs)+import Dhall.Syntax.Types+import Dhall.Syntax.Var+import Unsafe.Coerce                (unsafeCoerce)++import qualified Data.HashSet+import qualified Data.Text+import qualified Lens.Micro   as Lens+++-- | A traversal over the immediate sub-expressions of an expression.+subExpressions+    :: Applicative f => (Expr s a -> f (Expr s a)) -> Expr s a -> f (Expr s a)+subExpressions = subExpressionsWith (pure . Embed)+{-# INLINABLE subExpressions #-}++{-| A traversal over the immediate sub-expressions of an expression which+    allows mapping embedded values+-}+subExpressionsWith+    :: Applicative f => (a -> f (Expr s b)) -> (Expr s a -> f (Expr s b)) -> Expr s a -> f (Expr s b)+subExpressionsWith h _ (Embed a) = h a+subExpressionsWith _ f (Note a b) = Note a <$> f b+subExpressionsWith _ f (Let a b) = Let <$> bindingExprs f a <*> f b+subExpressionsWith _ f (Record a) = Record <$> traverse (recordFieldExprs f) a+subExpressionsWith _ f (RecordLit a) = RecordLit <$> traverse (recordFieldExprs f) a+subExpressionsWith _ f (Lam cs fb e) = Lam cs <$> functionBindingExprs f fb <*> f e+subExpressionsWith _ f (Field a b) = Field <$> f a <*> pure b+subExpressionsWith _ f expression = unsafeSubExpressions f expression+{-# INLINABLE subExpressionsWith #-}++{-| An internal utility used to implement transformations that require changing+    one of the type variables of the `Expr` type++    This utility only works because the implementation is partial, not+    handling the `Let`, `Note`, or `Embed` cases, which need to be handled by+    the caller.+-}+unsafeSubExpressions+    :: Applicative f => (Expr s a -> f (Expr t b)) -> Expr s a -> f (Expr t b)+unsafeSubExpressions _ (Const c) = pure (Const c)+unsafeSubExpressions _ (Var v) = pure (Var v)+unsafeSubExpressions f (Pi cs a b c) = Pi cs a <$> f b <*> f c+unsafeSubExpressions f (App a b) = App <$> f a <*> f b+unsafeSubExpressions f (Annot a b) = Annot <$> f a <*> f b+unsafeSubExpressions _ Bool = pure Bool+unsafeSubExpressions _ (BoolLit b) = pure (BoolLit b)+unsafeSubExpressions f (BoolAnd a b) = BoolAnd <$> f a <*> f b+unsafeSubExpressions f (BoolOr a b) = BoolOr <$> f a <*> f b+unsafeSubExpressions f (BoolEQ a b) = BoolEQ <$> f a <*> f b+unsafeSubExpressions f (BoolNE a b) = BoolNE <$> f a <*> f b+unsafeSubExpressions f (BoolIf a b c) = BoolIf <$> f a <*> f b <*> f c+unsafeSubExpressions _ Bytes = pure Bytes+unsafeSubExpressions _ (BytesLit a) = pure (BytesLit a)+unsafeSubExpressions _ Natural = pure Natural+unsafeSubExpressions _ (NaturalLit n) = pure (NaturalLit n)+unsafeSubExpressions _ NaturalFold = pure NaturalFold+unsafeSubExpressions _ NaturalBuild = pure NaturalBuild+unsafeSubExpressions _ NaturalIsZero = pure NaturalIsZero+unsafeSubExpressions _ NaturalEven = pure NaturalEven+unsafeSubExpressions _ NaturalOdd = pure NaturalOdd+unsafeSubExpressions _ NaturalToInteger = pure NaturalToInteger+unsafeSubExpressions _ NaturalShow = pure NaturalShow+unsafeSubExpressions _ NaturalSubtract = pure NaturalSubtract+unsafeSubExpressions f (NaturalPlus a b) = NaturalPlus <$> f a <*> f b+unsafeSubExpressions f (NaturalTimes a b) = NaturalTimes <$> f a <*> f b+unsafeSubExpressions _ Integer = pure Integer+unsafeSubExpressions _ (IntegerLit n) = pure (IntegerLit n)+unsafeSubExpressions _ IntegerClamp = pure IntegerClamp+unsafeSubExpressions _ IntegerNegate = pure IntegerNegate+unsafeSubExpressions _ IntegerShow = pure IntegerShow+unsafeSubExpressions _ IntegerToDouble = pure IntegerToDouble+unsafeSubExpressions _ Double = pure Double+unsafeSubExpressions _ (DoubleLit n) = pure (DoubleLit n)+unsafeSubExpressions _ DoubleShow = pure DoubleShow+unsafeSubExpressions _ Text = pure Text+unsafeSubExpressions f (TextLit chunks) = TextLit <$> chunkExprs f chunks+unsafeSubExpressions f (TextAppend a b) = TextAppend <$> f a <*> f b+unsafeSubExpressions _ TextReplace = pure TextReplace+unsafeSubExpressions _ TextShow = pure TextShow+unsafeSubExpressions _ Date = pure Date+unsafeSubExpressions _ (DateLiteral a) = pure (DateLiteral a)+unsafeSubExpressions _ DateShow = pure DateShow+unsafeSubExpressions _ Time = pure Time+unsafeSubExpressions _ (TimeLiteral a b) = pure (TimeLiteral a b)+unsafeSubExpressions _ TimeShow = pure TimeShow+unsafeSubExpressions _ TimeZone = pure TimeZone+unsafeSubExpressions _ (TimeZoneLiteral a) = pure (TimeZoneLiteral a)+unsafeSubExpressions _ TimeZoneShow = pure TimeZoneShow+unsafeSubExpressions _ List = pure List+unsafeSubExpressions f (ListLit a b) = ListLit <$> traverse f a <*> traverse f b+unsafeSubExpressions f (ListAppend a b) = ListAppend <$> f a <*> f b+unsafeSubExpressions _ ListBuild = pure ListBuild+unsafeSubExpressions _ ListFold = pure ListFold+unsafeSubExpressions _ ListLength = pure ListLength+unsafeSubExpressions _ ListHead = pure ListHead+unsafeSubExpressions _ ListLast = pure ListLast+unsafeSubExpressions _ ListIndexed = pure ListIndexed+unsafeSubExpressions _ ListReverse = pure ListReverse+unsafeSubExpressions _ Optional = pure Optional+unsafeSubExpressions f (Some a) = Some <$> f a+unsafeSubExpressions _ None = pure None+unsafeSubExpressions f (Union a) = Union <$> traverse (traverse f) a+unsafeSubExpressions f (Combine cs a b c) = Combine cs a <$> f b <*> f c+unsafeSubExpressions f (CombineTypes cs a b) = CombineTypes cs <$> f a <*> f b+unsafeSubExpressions f (Prefer cs a b c) = Prefer cs <$> pure a <*> f b <*> f c+unsafeSubExpressions f (RecordCompletion a b) = RecordCompletion <$> f a <*> f b+unsafeSubExpressions f (Merge a b t) = Merge <$> f a <*> f b <*> traverse f t+unsafeSubExpressions f (ToMap a t) = ToMap <$> f a <*> traverse f t+unsafeSubExpressions f (ShowConstructor a) = ShowConstructor <$> f a+unsafeSubExpressions f (Project a b) = Project <$> f a <*> traverse f b+unsafeSubExpressions f (Assert a) = Assert <$> f a+unsafeSubExpressions f (Equivalent cs a b) = Equivalent cs <$> f a <*> f b+unsafeSubExpressions f (With a b c) = With <$> f a <*> pure b <*> f c+unsafeSubExpressions f (ImportAlt l r) = ImportAlt <$> f l <*> f r+unsafeSubExpressions _ (Let {}) = unhandledConstructor "Let"+unsafeSubExpressions _ (Note {}) = unhandledConstructor "Note"+unsafeSubExpressions _ (Embed {}) = unhandledConstructor "Embed"+unsafeSubExpressions _ (Record {}) = unhandledConstructor "Record"+unsafeSubExpressions _ (RecordLit {}) = unhandledConstructor "RecordLit"+unsafeSubExpressions _ (Lam {}) = unhandledConstructor "Lam"+unsafeSubExpressions _ (Field {}) = unhandledConstructor "Field"+{-# INLINABLE unsafeSubExpressions #-}++unhandledConstructor :: Text -> a+unhandledConstructor constructor =+    internalError+        (   "Dhall.Syntax.unsafeSubExpressions: Unhandled "+        <>  constructor+        <>  " construtor"+        )++-- | Remove all `Note` constructors from an `Expr` (i.e. de-`Note`)+--+-- This also remove CharacterSet annotations.+denote :: Expr s a -> Expr t a+denote = \case+    Note _ b -> denote b+    Let a b -> Let (denoteBinding a) (denote b)+    Embed a -> Embed a+    Combine _ _ b c -> Combine Nothing Nothing (denote b) (denote c)+    CombineTypes _ b c -> CombineTypes Nothing (denote b) (denote c)+    Prefer _ a b c -> Lens.over unsafeSubExpressions denote $ Prefer Nothing a b c+    Record a -> Record $ denoteRecordField <$> a+    RecordLit a -> RecordLit $ denoteRecordField <$> a+    Lam _ a b -> Lam Nothing (denoteFunctionBinding a) (denote b)+    Pi _ t a b -> Pi Nothing t (denote a) (denote b)+    Field a (FieldSelection _ b _) -> Field (denote a) (FieldSelection Nothing b Nothing)+    Equivalent _ a b -> Equivalent Nothing (denote a) (denote b)+    expression -> Lens.over unsafeSubExpressions denote expression+  where+    denoteRecordField (RecordField _ e _ _) = RecordField Nothing (denote e) Nothing Nothing++    denoteBinding (Binding _ c _ d _ e) =+        Binding Nothing c Nothing (fmap denoteBindingAnnotation d) Nothing (denote e)++    denoteBindingAnnotation (_, f) = (Nothing, denote f)++    denoteFunctionBinding (FunctionBinding _ l _ _ t) =+        FunctionBinding Nothing l Nothing Nothing (denote t)++-- | The \"opposite\" of `denote`, like @first absurd@ but faster+renote :: Expr Void a -> Expr s a+renote = unsafeCoerce+{-# INLINE renote #-}++{-| Remove any outermost `Note` constructors++    This is typically used when you want to get the outermost non-`Note`+    constructor without removing internal `Note` constructors+-}+shallowDenote :: Expr s a -> Expr s a+shallowDenote (Note _ e) = shallowDenote e+shallowDenote         e  = e++-- | The set of reserved keywords according to the @keyword@ rule in the grammar+reservedKeywords :: HashSet Text+reservedKeywords =+    Data.HashSet.fromList+        [ "if"+        , "then"+        , "else"+        , "let"+        , "in"+        , "using"+        , "missing"+        , "as"+        , "Infinity"+        , "NaN"+        , "merge"+        , "Some"+        , "toMap"+        , "assert"+        , "forall"+        , "with"+        ]++-- | The set of reserved identifiers for the Dhall language+-- | Contains also all keywords from "reservedKeywords"+reservedIdentifiers :: HashSet Text+reservedIdentifiers = reservedKeywords <>+    Data.HashSet.fromList+        [ -- Builtins according to the `builtin` rule in the grammar+          "Natural/fold"+        , "Natural/build"+        , "Natural/isZero"+        , "Natural/even"+        , "Natural/odd"+        , "Natural/toInteger"+        , "Natural/show"+        , "Natural/subtract"+        , "Integer"+        , "Integer/clamp"+        , "Integer/negate"+        , "Integer/show"+        , "Integer/toDouble"+        , "Integer/show"+        , "Natural/subtract"+        , "Double/show"+        , "List/build"+        , "List/fold"+        , "List/length"+        , "List/head"+        , "List/last"+        , "List/indexed"+        , "List/reverse"+        , "Text/replace"+        , "Text/show"+        , "Date/show"+        , "Time/show"+        , "TimeZone/show"+        , "Bool"+        , "Bytes"+        , "True"+        , "False"+        , "Optional"+        , "None"+        , "Natural"+        , "Integer"+        , "Double"+        , "Text"+        , "Date"+        , "Time"+        , "TimeZone"+        , "List"+        , "Type"+        , "Kind"+        , "Sort"+        ]++{-| `shift` is used by both normalization and type-checking to avoid variable+    capture by shifting variable indices++    For example, suppose that you were to normalize the following expression:++> λ(a : Type) → λ(x : a) → (λ(y : a) → λ(x : a) → y) x++    If you were to substitute @y@ with @x@ without shifting any variable+    indices, then you would get the following incorrect result:++> λ(a : Type) → λ(x : a) → λ(x : a) → x  -- Incorrect normalized form++    In order to substitute @x@ in place of @y@ we need to `shift` @x@ by @1@ in+    order to avoid being misinterpreted as the @x@ bound by the innermost+    lambda.  If we perform that `shift` then we get the correct result:++> λ(a : Type) → λ(x : a) → λ(x : a) → x@1++    As a more worked example, suppose that you were to normalize the following+    expression:++>     λ(a : Type)+> →   λ(f : a → a → a)+> →   λ(x : a)+> →   λ(x : a)+> →   (λ(x : a) → f x x@1) x@1++    The correct normalized result would be:++>     λ(a : Type)+> →   λ(f : a → a → a)+> →   λ(x : a)+> →   λ(x : a)+> →   f x@1 x++    The above example illustrates how we need to both increase and decrease+    variable indices as part of substitution:++    * We need to increase the index of the outer @x\@1@ to @x\@2@ before we+      substitute it into the body of the innermost lambda expression in order+      to avoid variable capture.  This substitution changes the body of the+      lambda expression to @(f x\@2 x\@1)@++    * We then remove the innermost lambda and therefore decrease the indices of+      both @x@s in @(f x\@2 x\@1)@ to @(f x\@1 x)@ in order to reflect that one+      less @x@ variable is now bound within that scope++    Formally, @(shift d (V x n) e)@ modifies the expression @e@ by adding @d@ to+    the indices of all variables named @x@ whose indices are greater than+    @(n + m)@, where @m@ is the number of bound variables of the same name+    within that scope++    In practice, @d@ is always @1@ or @-1@ because we either:++    * increment variables by @1@ to avoid variable capture during substitution+    * decrement variables by @1@ when deleting lambdas after substitution++    @n@ starts off at @0@ when substitution begins and increments every time we+    descend into a lambda or let expression that binds a variable of the same+    name in order to avoid shifting the bound variables by mistake.+-}+shift :: Int -> Var -> Expr s a -> Expr s a+shift d (V x n) (Var (V x' n')) = Var (V x' n'')+  where+    n'' = if x == x' && n <= n' then n' + d else n'+shift d (V x n) (Lam cs (FunctionBinding src0 x' src1 src2 _A) b) =+    Lam cs (FunctionBinding src0 x' src1 src2 _A') b'+  where+    _A' = shift d (V x n ) _A+    b'  = shift d (V x n') b+      where+        n' = if x == x' then n + 1 else n+shift d (V x n) (Pi cs x' _A _B) = Pi cs x' _A' _B'+  where+    _A' = shift d (V x n ) _A+    _B' = shift d (V x n') _B+      where+        n' = if x == x' then n + 1 else n+shift d (V x n) (Let (Binding src0 f src1 mt src2 r) e) =+    Let (Binding src0 f src1 mt' src2 r') e'+  where+    e' = shift d (V x n') e+      where+        n' = if x == f then n + 1 else n++    mt' = fmap (fmap (shift d (V x n))) mt+    r'  =             shift d (V x n)  r+shift d v expression = Lens.over subExpressions (shift d v) expression++_ERROR :: String+_ERROR = "\ESC[1;31mError\ESC[0m"++{-| Utility function used to throw internal errors that should never happen+    (in theory) but that are not enforced by the type system+-}+internalError :: Data.Text.Text -> forall b . b+internalError text = error (unlines+    [ _ERROR <> ": Compiler bug                                                        "+    , "                                                                                "+    , "Explanation: This error message means that there is a bug in the Dhall compiler."+    , "You didn't do anything wrong, but if you would like to see this problem fixed   "+    , "then you should report the bug at:                                              "+    , "                                                                                "+    , "https://github.com/dhall-lang/dhall-haskell/issues                              "+    , "                                                                                "+    , "Please include the following text in your bug report:                           "+    , "                                                                                "+    , "```                                                                             "+    , Data.Text.unpack text <> "                                                       "+    , "```                                                                             "+    ] )
+ src/Dhall/Syntax/Operations.hs-boot view
@@ -0,0 +1,5 @@+module Dhall.Syntax.Operations where++import Dhall.Syntax.Expr (Expr)++unsafeSubExpressions :: Applicative f => (Expr s a -> f (Expr t b)) -> Expr s a -> f (Expr t b)
+ src/Dhall/Syntax/RecordField.hs view
@@ -0,0 +1,93 @@+{-# LANGUAGE DeriveGeneric #-}++module Dhall.Syntax.RecordField+    ( RecordField(..)+    , makeRecordField++      -- * Optics+    , recordFieldExprs+    ) where++import {-# SOURCE #-} Dhall.Syntax.Expr (Expr)+import                GHC.Generics      (Generic)++-- | Record the field of a record-type and record-literal expression.+-- The reason why we use the same ADT for both of them is because they store+-- the same information.+--+-- For example,+--+-- > { {- A -} x {- B -} : {- C -} T }+--+-- ... or+--+-- > { {- A -} x {- B -} = {- C -} T }+--+-- will be instantiated as follows:+--+-- * @recordFieldSrc0@ corresponds to the @A@ comment.+-- * @recordFieldValue@ is @"T"@+-- * @recordFieldSrc1@ corresponds to the @B@ comment.+-- * @recordFieldSrc2@ corresponds to the @C@ comment.+--+-- Although the @A@ comment isn't annotating the @"T"@ Record Field,+-- this is the best place to keep these comments.+--+-- Note that @recordFieldSrc2@ is always 'Nothing' when the 'RecordField' is for+-- a punned entry, because there is no @=@ sign. For example,+--+-- > { {- A -} x {- B -} }+--+-- will be instantiated as follows:+--+-- * @recordFieldSrc0@ corresponds to the @A@ comment.+-- * @recordFieldValue@ corresponds to @(Var "x")@+-- * @recordFieldSrc1@ corresponds to the @B@ comment.+-- * @recordFieldSrc2@ will be 'Nothing'+--+-- The labels involved in a record using dot-syntax like in this example:+--+-- > { {- A -} a {- B -} . {- C -} b {- D -} . {- E -} c {- F -} = {- G -} e }+--+-- will be instantiated as follows:+--+-- * For both the @a@ and @b@ field, @recordfieldSrc2@ is 'Nothing'+-- * For the @a@ field:+--   * @recordFieldSrc0@ corresponds to the @A@ comment+--   * @recordFieldSrc1@ corresponds to the @B@ comment+-- * For the @b@ field:+--   * @recordFieldSrc0@ corresponds to the @C@ comment+--   * @recordFieldSrc1@ corresponds to the @D@ comment+-- * For the @c@ field:+--   * @recordFieldSrc0@ corresponds to the @E@ comment+--   * @recordFieldSrc1@ corresponds to the @F@ comment+--   * @recordFieldSrc2@ corresponds to the @G@ comment+--+-- That is, for every label except the last one the semantics of+-- @recordFieldSrc0@ and @recordFieldSrc1@ are the same from a regular record+-- label but @recordFieldSrc2@ is always 'Nothing'. For the last keyword, all+-- srcs are 'Just'+data RecordField s a = RecordField+    { recordFieldSrc0  :: Maybe s+    , recordFieldValue :: Expr s a+    , recordFieldSrc1  :: Maybe s+    , recordFieldSrc2  :: Maybe s+    } deriving Generic++-- | Construct a 'RecordField' with no src information+makeRecordField :: Expr s a -> RecordField s a+makeRecordField e = RecordField Nothing e Nothing Nothing++{-| Traverse over the immediate 'Expr' children in a 'RecordField'.+-}+recordFieldExprs+    :: Applicative f+    => (Expr s a -> f (Expr s b))+    -> RecordField s a -> f (RecordField s b)+recordFieldExprs f (RecordField s0 e s1 s2) =+    RecordField+        <$> pure s0+        <*> f e+        <*> pure s1+        <*> pure s2+{-# INLINABLE recordFieldExprs #-}
+ src/Dhall/Syntax/Types.hs view
@@ -0,0 +1,55 @@+{-# LANGUAGE DeriveGeneric #-}++module Dhall.Syntax.Types+    ( DhallDouble(..)+    , PreferAnnotation(..)+    , FieldSelection(..)+    , makeFieldSelection+    , WithComponent(..)+    ) where++import Data.Text    (Text)+import GHC.Generics (Generic)++-- | This wrapper around 'Prelude.Double' exists for its 'Eq' instance which is+-- defined via the binary encoding of Dhall @Double@s.+newtype DhallDouble = DhallDouble { getDhallDouble :: Double }+    deriving Generic++-- | Used to record the origin of a @//@ operator (i.e. from source code or a+-- product of desugaring)+data PreferAnnotation+    = PreferFromSource+    | PreferFromCompletion+    deriving Generic++-- | Record the field on a selector-expression+--+-- For example,+--+-- > e . {- A -} x {- B -}+--+-- … will be instantiated as follows:+--+-- * @fieldSelectionSrc0@ corresponds to the @A@ comment+-- * @fieldSelectionLabel@ corresponds to @x@+-- * @fieldSelectionSrc1@ corresponds to the @B@ comment+--+-- Given our limitation that not all expressions recover their whitespaces, the+-- purpose of @fieldSelectionSrc1@ is to save the 'Text.Megaparsec.SourcePos'+-- where the @fieldSelectionLabel@ ends, but we /still/ use a+-- 'Maybe Dhall.Src.Src' (@s = 'Dhall.Src.Src'@) to be consistent with similar+-- data types such as 'Dhall.Syntax.Binding.Binding', for example.+data FieldSelection s = FieldSelection+    { fieldSelectionSrc0 :: Maybe s+    , fieldSelectionLabel :: !Text+    , fieldSelectionSrc1 :: Maybe s+    } deriving Generic++-- | Smart constructor for 'FieldSelection' with no src information+makeFieldSelection :: Text -> FieldSelection s+makeFieldSelection t = FieldSelection Nothing t Nothing++-- | A path component for a @with@ expression+data WithComponent = WithLabel Text | WithQuestion+    deriving Generic
+ src/Dhall/Syntax/Types.hs-boot view
@@ -0,0 +1,14 @@+{-# LANGUAGE StandaloneKindSignatures #-}++module Dhall.Syntax.Types where++import Data.Kind (Type)++data DhallDouble++data PreferAnnotation++type FieldSelection :: Type -> Type+data FieldSelection s++data WithComponent
+ src/Dhall/Syntax/Var.hs view
@@ -0,0 +1,47 @@+{-# LANGUAGE DeriveGeneric #-}++module Dhall.Syntax.Var+    ( Var(..)+    ) where++import Data.String  (IsString (..))+import Data.Text    (Text)+import GHC.Generics (Generic)++{-| Label for a bound variable++    The `Data.Text.Text` field is the variable's name (i.e. \"@x@\").++    The `Int` field disambiguates variables with the same name if there are+    multiple bound variables of the same name in scope.  Zero refers to the+    nearest bound variable and the index increases by one for each bound+    variable of the same name going outward.  The following diagram may help:++>                               ┌──refers to──┐+>                               │             │+>                               v             │+> λ(x : Type) → λ(y : Type) → λ(x : Type) → x@0+>+> ┌─────────────────refers to─────────────────┐+> │                                           │+> v                                           │+> λ(x : Type) → λ(y : Type) → λ(x : Type) → x@1++    This `Int` behaves like a De Bruijn index in the special case where all+    variables have the same name.++    You can optionally omit the index if it is @0@:++>                               ┌─refers to─┐+>                               │           │+>                               v           │+> λ(x : Type) → λ(y : Type) → λ(x : Type) → x++    Zero indices are omitted when pretty-printing @Var@s and non-zero indices+    appear as a numeric suffix.+-}+data Var = V Text !Int+    deriving Generic++instance IsString Var where+    fromString str = V (fromString str) 0
src/Dhall/TH.hs view
@@ -1,16 +1,83 @@-{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE CPP               #-}+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternGuards     #-}+{-# LANGUAGE RecordWildCards   #-}+{-# LANGUAGE TemplateHaskell   #-} -{-| This module provides `staticDhallExpression` which can be used to resolve-    all of an expression’s imports at compile time, allowing one to reference-    Dhall expressions from Haskell without having a runtime dependency on the-    location of Dhall files.+-- | Template Haskell utilities+module Dhall.TH+    ( -- * Embedding Dhall in Haskell+      staticDhallExpression+    , dhall+      -- * Generating Haskell from Dhall expressions+    , makeHaskellTypeFromUnion+    , makeHaskellTypes+    , makeHaskellTypesWith+    , HaskellType(..)+    , GenerateOptions(..)+    , defaultGenerateOptions+    ) where +import Control.Monad             (forM_)+import Data.Bifunctor            (first)+import Data.Text                 (Text)+import Dhall                     (FromDhall, ToDhall)+import Dhall.Syntax              (Expr (..), FunctionBinding (..), Var (..))+import GHC.Generics              (Generic)+import Language.Haskell.TH.Quote (QuasiQuoter (..), dataToExpQ)+import Lens.Micro.Extras         (view)+import Prettyprinter             (Pretty)++import Language.Haskell.TH.Syntax+    ( Bang (..)+    , Body (..)+    , Con (..)+    , Dec (..)+    , Exp (..)+    , Match (..)+    , Pat (..)+    , Q+    , SourceStrictness (..)+    , SourceUnpackedness (..)+    , Type (..)+    )++import Language.Haskell.TH.Syntax (DerivClause (..), DerivStrategy (..))++import qualified Data.List                   as List+import qualified Data.Map                    as Map+import qualified Data.Set                    as Set+import qualified Data.Text                   as Text+import qualified Data.Time                   as Time+import qualified Data.Typeable               as Typeable+import qualified Dhall+import qualified Dhall.Core                  as Core+import qualified Dhall.Import+import qualified Dhall.Map+import qualified Dhall.Pretty+import qualified Dhall.Util+import qualified GHC.IO.Encoding+import qualified Language.Haskell.TH.Syntax  as TH+import qualified Numeric.Natural+import qualified Prettyprinter.Render.String as Pretty+import qualified System.IO+++{-| This fully resolves, type checks, and normalizes the expression, so the+    resulting AST is self-contained.++    This can be used to resolve all of an expression’s imports at compile time,+    allowing one to reference Dhall expressions from Haskell without having a+    runtime dependency on the location of Dhall files.+     For example, given a file @".\/Some\/Type.dhall"@ containing      > < This : Natural | Other : ../Other/Type.dhall > -    ... rather than duplicating the AST manually in a Haskell `Type`, you can-    do:+    ... rather than duplicating the AST manually in a Haskell `Dhall.Type`, you+    can do:      > Dhall.Type     > (\case@@ -22,28 +89,547 @@     at compile time with all imports resolved, making it easy to keep your Dhall     configs and Haskell interpreters in sync. -}-module Dhall.TH-    ( -- * Template Haskell-      staticDhallExpression-    ) where+staticDhallExpression :: Text -> Q Exp+staticDhallExpression text = do+    TH.runIO (GHC.IO.Encoding.setLocaleEncoding System.IO.utf8) -import Data.Typeable-import Language.Haskell.TH.Quote (dataToExpQ) -- 7.10 compatibility.-import Language.Haskell.TH.Syntax+    (expression, status) <- TH.runIO $ do+        parsed <- Dhall.parseWithSettings Dhall.defaultInputSettings text -import qualified Data.Text as Text-import qualified Dhall-import qualified GHC.IO.Encoding-import qualified System.IO+        (resolved, status) <- Dhall.resolveAndStatusWithSettings Dhall.defaultInputSettings parsed --- | This fully resolves, type checks, and normalizes the expression, so the---   resulting AST is self-contained.-staticDhallExpression :: Text.Text -> Q Exp-staticDhallExpression text = do-    runIO (GHC.IO.Encoding.setLocaleEncoding System.IO.utf8)-    expression <- runIO (Dhall.inputExpr text)-    dataToExpQ (\a -> liftText <$> cast a) expression+        _ <- 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)) . 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)+    => [Var]+    -> [HaskellType (Expr s a)]+    -- ^ All Dhall-derived data declarations+    --+    -- Used to replace complex types with references to one of these+    -- data declarations when the types match+    -> Expr s a+    -- ^ Dhall expression to convert to a simple Haskell type+    -> Q Type+toNestedHaskellType typeParams haskellTypes = loop+  where+    predicate dhallType haskellType = Core.judgmentallyEqual (code haskellType) dhallType++    document dhallType =+      mconcat+      [ "Unsupported nested type\n"+      , "                                                                                \n"+      , "Explanation: Not all Dhall types can be nested within Haskell datatype          \n"+      , "declarations.  Specifically, only the following simple Dhall types are supported\n"+      , "as a nested type inside of a data declaration:                                  \n"+      , "                                                                                \n"+      , "• ❰Bool❱                                                                        \n"+      , "• ❰Double❱                                                                      \n"+      , "• ❰Integer❱                                                                     \n"+      , "• ❰Natural❱                                                                     \n"+      , "• ❰Text❱                                                                        \n"+      , "• ❰Date❱                                                                        \n"+      , "• ❰TimeOfDay❱                                                                   \n"+      , "• ❰TimeZone❱                                                                    \n"+      , "• ❰List a❱     (where ❰a❱ is also a valid nested type)                          \n"+      , "• ❰Optional a❱ (where ❰a❱ is also a valid nested type)                          \n"+      , "• Another matching datatype declaration                                         \n"+      , "• A bound type variable                                                         \n"+      , "                                                                                \n"+      , "The Haskell datatype generation logic encountered the following Dhall type:     \n"+      , "                                                                                \n"+      , " " <> Dhall.Util.insert dhallType <> "\n"+      , "                                                                                \n"+      , "... which did not fit any of the above criteria."+      ]++    message dhallType = Pretty.renderString (Dhall.Pretty.layout (document dhallType))++    loop dhallType = case dhallType of+        Bool ->+            return (ConT ''Bool)++        Double ->+            return (ConT ''Double)++        Integer ->+            return (ConT ''Integer)++        Natural ->+            return (ConT ''Numeric.Natural.Natural)++        Text ->+            return (ConT ''Text)++        Date ->+            return (ConT ''Time.Day)++        Time ->+            return (ConT ''Time.TimeOfDay)++        TimeZone ->+            return (ConT ''Time.TimeZone)++        App List dhallElementType -> do+            haskellElementType <- loop dhallElementType++            return (AppT (ConT ''[]) haskellElementType)++        App Optional dhallElementType -> do+            haskellElementType <- loop dhallElementType++            return (AppT (ConT ''Maybe) haskellElementType)++        App dhallAppType dhallElementType -> do+            haskellAppType <- loop dhallAppType+            haskellElementType <- loop dhallElementType++            return (AppT haskellAppType haskellElementType)++        Var v+            | Just (V param index) <- List.find (v ==) typeParams -> do+                let name = TH.mkName $ (Text.unpack param) ++ (show index)++                return (VarT name)++            | otherwise -> fail $ message v++        _   | Just haskellType <- List.find (predicate dhallType) haskellTypes -> do+                let name = TH.mkName (Text.unpack (typeName haskellType))++                return (ConT name)+            | otherwise -> fail $ message dhallType++-- | A deriving clause for `Generic`.+derivingGenericClause :: DerivClause+derivingGenericClause = DerivClause (Just StockStrategy) [ ConT ''Generic ]++-- | Generates a `FromDhall` instances.+fromDhallInstance+    :: TH.Name -- ^ The name of the type the instances is for+    -> Q Exp       -- ^ A TH splice generating some `Dhall.InterpretOptions`+    -> Q [Dec]+fromDhallInstance n interpretOptions = [d|+    instance FromDhall $(pure $ ConT n) where+        autoWith = Dhall.genericAutoWithInputNormalizer $(interpretOptions)+    |]++-- | Generates a `ToDhall` instances.+toDhallInstance+    :: TH.Name -- ^ The name of the type the instances is for+    -> Q Exp       -- ^ A TH splice generating some `Dhall.InterpretOptions`+    -> Q [Dec]+toDhallInstance n interpretOptions = [d|+    instance ToDhall $(pure $ ConT n) where+        injectWith = Dhall.genericToDhallWithInputNormalizer $(interpretOptions)+    |]++-- | Convert a Dhall type to the corresponding Haskell datatype declaration+toDeclaration+    :: (Eq a, Pretty a)+    => GenerateOptions+    -> [HaskellType (Expr s a)]+    -> HaskellType (Expr s a)+    -> Q [Dec]+toDeclaration generateOptions@GenerateOptions{..} haskellTypes typ =+    case typ of+        SingleConstructor{..} -> uncurry (fromSingle typeName constructorName) $ getTypeParams code+        MultipleConstructors{..} -> uncurry (fromMulti typeName) $ getTypeParams code+    where+        getTypeParams = first numberConsecutive .  getTypeParams_ []++        getTypeParams_ acc (Lam _ (FunctionBinding _ v _ _ _) rest) = getTypeParams_ (v:acc) rest+        getTypeParams_ acc rest = (acc, rest)++        derivingClauses = [ derivingGenericClause | generateFromDhallInstance || generateToDhallInstance ]++        interpretOptions = generateToInterpretOptions generateOptions typ++#if MIN_VERSION_template_haskell(2,21,0)+        toTypeVar (V n i) = TH.PlainTV (TH.mkName (Text.unpack n ++ show i)) TH.BndrReq+#elif MIN_VERSION_template_haskell(2,17,0)+        toTypeVar (V n i) = TH.PlainTV (TH.mkName (Text.unpack n ++ show i)) ()+#else+        toTypeVar (V n i) = TH.PlainTV (TH.mkName (Text.unpack n ++ show i))+#endif++        toDataD typeName typeParams constructors = do+            let name = TH.mkName (Text.unpack typeName)++            let params = fmap toTypeVar typeParams++            fmap concat . sequence $+                [pure [DataD [] name params Nothing constructors derivingClauses]] <>+                [ fromDhallInstance name interpretOptions | generateFromDhallInstance ] <>+                [ toDhallInstance name interpretOptions | generateToDhallInstance ]++        fromSingle typeName constructorName typeParams dhallType = do+            constructor <- toConstructor typeParams generateOptions haskellTypes typeName (constructorName, Just dhallType)++            toDataD typeName typeParams [constructor]++        fromMulti typeName typeParams dhallType = case dhallType of+            Union kts -> do+                constructors <- traverse (toConstructor typeParams generateOptions haskellTypes typeName) (Dhall.Map.toList kts)++                toDataD typeName typeParams constructors++            _ -> fail $ message dhallType++        message dhallType = Pretty.renderString (Dhall.Pretty.layout $ document dhallType)++        document dhallType =+            mconcat+                [ "Dhall.TH.makeHaskellTypes: Not a union type\n"+                , "                                                                                \n"+                , "Explanation: This function expects the ❰code❱ field of ❰MultipleConstructors❱ to\n"+                , "evaluate to a union type.                                                       \n"+                , "                                                                                \n"+                , "For example, this is a valid Dhall union type that this function would accept:  \n"+                , "                                                                                \n"+                , "                                                                                \n"+                , "    ┌──────────────────────────────────────────────────────────────────┐        \n"+                , "    │ Dhall.TH.makeHaskellTypes (MultipleConstructors \"T\" \"< A | B >\") │        \n"+                , "    └──────────────────────────────────────────────────────────────────┘        \n"+                , "                                                                                \n"+                , "                                                                                \n"+                , "... which corresponds to this Haskell type declaration:                         \n"+                , "                                                                                \n"+                , "                                                                                \n"+                , "    ┌────────────────┐                                                          \n"+                , "    │ data T = A | B │                                                          \n"+                , "    └────────────────┘                                                          \n"+                , "                                                                                \n"+                , "                                                                                \n"+                , "... but the following Dhall type is rejected due to being a bare record type:   \n"+                , "                                                                                \n"+                , "                                                                                \n"+                , "    ┌──────────────────────────────────────────────┐                            \n"+                , "    │ Dhall.TH.makeHaskellTypes \"T\" \"{ x : Bool }\" │  Not valid                 \n"+                , "    └──────────────────────────────────────────────┘                            \n"+                , "                                                                                \n"+                , "                                                                                \n"+                , "The Haskell datatype generation logic encountered the following Dhall type:     \n"+                , "                                                                                \n"+                , " " <> Dhall.Util.insert dhallType <> "\n"+                , "                                                                                \n"+                , "... which is not a union type."+                ]++-- | Number each variable, starting at 0+numberConsecutive :: [Text.Text] -> [Var]+numberConsecutive = snd . List.mapAccumR go Map.empty . reverse+  where+      go m k =+          let (i, m') = Map.updateLookupWithKey (\_ j -> Just $ j + 1) k m+          in maybe ((Map.insert k 0 m'), (V k 0)) (\i' -> (m', (V k i'))) i++-- | Convert a Dhall type to the corresponding Haskell constructor+toConstructor+    :: (Eq a, Pretty a)+    => [Var]+    -> GenerateOptions+    -> [HaskellType (Expr s a)]+    -> Text+    -- ^ typeName+    -> (Text, Maybe (Expr s a))+    -- ^ @(constructorName, fieldType)@+    -> Q Con+toConstructor typeParams GenerateOptions{..} haskellTypes outerTypeName (constructorName, maybeAlternativeType) = do+    let name = TH.mkName (Text.unpack $ constructorModifier constructorName)++    let strictness = if makeStrict then SourceStrict else NoSourceStrictness++    let bang = Bang NoSourceUnpackedness strictness++    case maybeAlternativeType of+        Just dhallType+            | let predicate haskellType =+                    Core.judgmentallyEqual (code haskellType) dhallType+                    && typeName haskellType /= outerTypeName+            , Just haskellType <- List.find predicate haskellTypes -> do+                let innerName =+                        TH.mkName (Text.unpack (typeName haskellType))++                return (NormalC name [ (bang, ConT innerName) ])++        Just (Record kts) -> do+            let process (key, dhallFieldType) = do+                    haskellFieldType <- toNestedHaskellType typeParams haskellTypes dhallFieldType++                    return (TH.mkName (Text.unpack $ fieldModifier key), bang, haskellFieldType)++            varBangTypes <- traverse process (Dhall.Map.toList $ Core.recordFieldValue <$> kts)++            return (RecC name varBangTypes)++        Just dhallAlternativeType -> do+            haskellAlternativeType <- toNestedHaskellType typeParams haskellTypes dhallAlternativeType++            return (NormalC name [ (bang, haskellAlternativeType) ])++        Nothing ->+            return (NormalC name [])++-- | Generate a Haskell datatype declaration from a Dhall union type where+-- each union alternative corresponds to a Haskell constructor+--+-- For example, this Template Haskell splice:+--+-- > Dhall.TH.makeHaskellTypeFromUnion "T" "< A : { x : Bool } | B >"+--+-- ... generates this Haskell code:+--+-- > data T = A {x :: GHC.Types.Bool} | B+--+-- This is a special case of `Dhall.TH.makeHaskellTypes`:+--+-- > makeHaskellTypeFromUnion typeName code =+-- >     makeHaskellTypes [ MultipleConstructors{..} ]+makeHaskellTypeFromUnion+    :: Text+    -- ^ Name of the generated Haskell type+    -> Text+    -- ^ Dhall code that evaluates to a union type+    -> Q [Dec]+makeHaskellTypeFromUnion typeName code =+    makeHaskellTypes [ MultipleConstructors{..} ]++-- | Used by `makeHaskellTypes` and `makeHaskellTypesWith` to specify how to+-- generate Haskell types.+data HaskellType code+    -- | Generate a Haskell type with more than one constructor from a Dhall+    -- union type.+    = MultipleConstructors+        { typeName :: Text+        -- ^ Name of the generated Haskell type+        , code :: code+        -- ^ Dhall code that evaluates to a union type+        }+    -- | Generate a Haskell type with one constructor from any Dhall type.+    --+    -- To generate a constructor with multiple named fields, supply a Dhall+    -- record type.  This does not support more than one anonymous field.+    | SingleConstructor+        { typeName :: Text+        -- ^ Name of the generated Haskell type+        , constructorName :: Text+        -- ^ Name of the constructor+        , code :: code+        -- ^ Dhall code that evaluates to a type+        }+    deriving (Functor, Foldable, Traversable)++-- | This data type holds various options that let you control several aspects+-- how Haskell code is generated. In particular you can+--+--   * disable the generation of `FromDhall`/`ToDhall` instances.+--   * modify how a Dhall union field translates to a Haskell data constructor.+data GenerateOptions = GenerateOptions+    { constructorModifier :: Text -> Text+    -- ^ How to map a Dhall union field name to a Haskell constructor.+    -- Note: The `constructorName` of `SingleConstructor` will be passed to this function, too.+    , fieldModifier :: Text -> Text+    -- ^ How to map a Dhall record field names to a Haskell record field names.+    , generateFromDhallInstance :: Bool+    -- ^ Generate a `FromDhall` instance for the Haskell type+    , generateToDhallInstance :: Bool+    -- ^ Generate a `ToDhall` instance for the Haskell type+    , makeStrict :: Bool+    -- ^ Make all fields strict.+    }++-- | A default set of options used by `makeHaskellTypes`. That means:+--+--     * Constructors and fields are passed unmodified.+--     * Both `FromDhall` and `ToDhall` instances are generated.+--+--   Note: `From/ToDhall` should be `False` if importing higher-kinded types.+--   In these cases one should use a standalone declaration.+defaultGenerateOptions :: GenerateOptions+defaultGenerateOptions = GenerateOptions+    { constructorModifier = id+    , fieldModifier = id+    , generateFromDhallInstance = True+    , generateToDhallInstance = True+    , makeStrict = False+    }++-- | This function generates `Dhall.InterpretOptions` that can be used for the+--   marshalling of the Haskell type generated according to the `GenerateOptions`.+--   I.e. those `Dhall.InterpretOptions` reflect the mapping done by+--   `constructorModifier` and `fieldModifier` on the value level.+generateToInterpretOptions :: GenerateOptions -> HaskellType (Expr s a) -> Q Exp+generateToInterpretOptions GenerateOptions{..} haskellType = [| Dhall.InterpretOptions+    { Dhall.fieldModifier = \ $(pure nameP) ->+        $(toCases fieldModifier $ fields haskellType)+    , Dhall.constructorModifier = \ $(pure nameP) ->+        $(toCases constructorModifier $ constructors haskellType)+    , Dhall.singletonConstructors = Dhall.singletonConstructors Dhall.defaultInterpretOptions+    }|]+    where+        constructors :: HaskellType (Expr s a) -> [Text]+        constructors SingleConstructor{..} = [constructorName]+        constructors MultipleConstructors{..} | Union kts <- code = Dhall.Map.keys kts+        constructors _ = []++        fields :: HaskellType (Expr s a) -> [Text]+        fields SingleConstructor{..} | Record kts <- code = Dhall.Map.keys kts+        fields MultipleConstructors{..} | Union kts <- code = Set.toList $ mconcat+            [ Dhall.Map.keysSet kts'+            | (_, Just (Record kts')) <- Dhall.Map.toList kts+            ]+        fields _ = []++        toCases :: (Text -> Text) -> [Text] -> Q Exp+        toCases f xs = do+            err <- [| Core.internalError $ "Unmatched " <> Text.pack (show $(pure nameE)) |]+            pure $ CaseE nameE $ map mkMatch xs <> [Match WildP (NormalB err) []]+            where+                mkMatch n = Match (textToPat $ f n) (NormalB $ textToExp n) []++        nameE :: Exp+        nameE = TH.VarE $ TH.mkName "n"++        nameP :: Pat+        nameP = TH.VarP $ TH.mkName "n"++        textToExp :: Text -> Exp+        textToExp = TH.LitE . TH.StringL . Text.unpack++        textToPat :: Text -> Pat+        textToPat = TH.LitP . TH.StringL . Text.unpack++-- | Generate a Haskell datatype declaration with one constructor from a Dhall+-- type.+--+-- This comes in handy if you need to keep Dhall types and Haskell types in+-- sync.  You make the Dhall types the source of truth and use Template Haskell+-- to generate the matching Haskell type declarations from the Dhall types.+--+-- For example, given this Dhall code:+--+-- > -- ./Department.dhall+-- > < Sales | Engineering | Marketing >+--+-- > -- ./Employee.dhall+-- > { name : Text, department : ./Department.dhall }+--+-- ... this Template Haskell splice:+--+-- > {-# LANGUAGE DeriveAnyClass     #-}+-- > {-# LANGUAGE DeriveGeneric      #-}+-- > {-# LANGUAGE DerivingStrategies #-}+-- > {-# LANGUAGE OverloadedStrings  #-}+-- > {-# LANGUAGE TemplateHaskell    #-}+-- >+-- > Dhall.TH.makeHaskellTypes+-- >     [ MultipleConstructors "Department" "./tests/th/Department.dhall"+-- >     , SingleConstructor "Employee" "MakeEmployee" "./tests/th/Employee.dhall"+-- >     ]+--+-- ... generates this Haskell code:+--+-- > data Department = Engineering | Marketing | Sales+-- >   deriving stock (GHC.Generics.Generic)+-- >   deriving anyclass (Dhall.FromDhall, Dhall.ToDhall)+-- >+-- > data Employee+-- >   = MakeEmployee {department :: Department,+-- >                   name :: Data.Text.Internal.Text}+-- >   deriving stock (GHC.Generics.Generic)+-- >   deriving anyclass (Dhall.FromDhall, Dhall.ToDhall)+--+-- Carefully note that the conversion makes a best-effort attempt to+-- auto-detect when a Dhall type (like @./Employee.dhall@) refers to another+-- Dhall type (like @./Department.dhall@) and replaces that reference with the+-- corresponding Haskell type.+--+-- This Template Haskell splice requires you to enable the following extensions:+--+-- * @DeriveGeneric@+-- * @DerivingAnyClass@+-- * @DerivingStrategies@+--+-- By default, the generated types only derive `GHC.Generics.Generic`,+-- `Dhall.FromDhall`, and `Dhall.ToDhall`.  To add any desired instances (such+-- as `Eq`\/`Ord`\/`Show`), you can use the @StandaloneDeriving@ language+-- extension, like this:+--+-- > {-# LANGUAGE DeriveAnyClass     #-}+-- > {-# LANGUAGE DeriveGeneric      #-}+-- > {-# LANGUAGE DerivingStrategies #-}+-- > {-# LANGUAGE OverloadedStrings  #-}+-- > {-# LANGUAGE StandaloneDeriving #-}+-- > {-# LANGUAGE TemplateHaskell    #-}+-- >+-- > Dhall.TH.makeHaskellTypes+-- >     [ MultipleConstructors "Department" "./tests/th/Department.dhall"+-- >     , SingleConstructor "Employee" "MakeEmployee" "./tests/th/Employee.dhall"+-- >     ]+-- >+-- > deriving instance Eq   Department+-- > deriving instance Ord  Department+-- > deriving instance Show Department+-- >+-- > deriving instance Eq   Employee+-- > deriving instance Ord  Employee+-- > deriving instance Show Employee+makeHaskellTypes :: [HaskellType Text] -> Q [Dec]+makeHaskellTypes = makeHaskellTypesWith defaultGenerateOptions++-- | Like `makeHaskellTypes`, but with the ability to customize the generated+-- Haskell code by passing `GenerateOptions`.+--+-- For instance, `makeHaskellTypes` is implemented using this function:+--+-- > makeHaskellTypes = makeHaskellTypesWith defaultGenerateOptions+makeHaskellTypesWith :: GenerateOptions -> [HaskellType Text] -> Q [Dec]+makeHaskellTypesWith generateOptions haskellTypes = do+    TH.runIO (GHC.IO.Encoding.setLocaleEncoding System.IO.utf8)++    haskellTypes' <- traverse (traverse (TH.runIO . Dhall.inputExpr)) haskellTypes++    concat <$> traverse (toDeclaration generateOptions haskellTypes') haskellTypes'
+ src/Dhall/Tags.hs view
@@ -0,0 +1,269 @@+{-# LANGUAGE LambdaCase        #-}+{-# LANGUAGE OverloadedStrings #-}++-- | This module contains the implementation of the @dhall tags@ command++module Dhall.Tags+    ( generate+    ) where++import Control.Exception  (SomeException (..), handle)+import Data.List          (foldl', isSuffixOf)+import Data.Maybe         (fromMaybe)+import Data.Text          (Text)+import Data.Text.Encoding (encodeUtf8)+import Dhall.Map          (foldMapWithKey)+import Dhall.Parser       (exprFromText)+import Dhall.Src          (Src (srcStart))+import Dhall.Syntax       (Binding (..), Expr (..), RecordField (..))+import Dhall.Util         (Input (..))+import System.FilePath    (takeFileName, (</>))+import Text.Megaparsec    (sourceColumn, sourceLine, unPos)++import qualified Data.ByteString  as BS (length)+import qualified Data.Map         as M+import qualified Data.Text        as T+import qualified Data.Text.IO     as TIO+import qualified System.Directory as SD++{-+    Documentation for the etags format is not very informative and not very correct.+    You can find some documentation here:+    https://en.wikipedia.org/wiki/Ctags#Etags_2+    and you can also check the source code here:+    http://cvs.savannah.gnu.org/viewvc/vtags/vtags/vtags.el?view=markup+-}++data LineColumn = LC+    { _lcLine :: Int+      -- ^ line number, starting from 1, where to find the tag+    , _lcColumn :: Int+      -- ^ column of line where tag is+    } deriving (Eq, Ord, Show)++data LineOffset = LO+    { loLine :: Int+      -- ^ line number, starting from 1, where to find the tag+    , loOffset :: Int+      -- ^ byte offset from start of file. Not sure if any editor uses it+    } deriving (Eq, Ord, Show)++newtype Tags = Tags (M.Map FilePath [(LineOffset, Tag)])++instance Semigroup Tags where+    (Tags ts1) <> (Tags ts2) = Tags (M.unionWith (<>) ts1 ts2)++instance Monoid Tags where+    mempty = Tags M.empty++{-| For example, for the line: @let foo = \"foo\"@ the tag is:+    > Tag "let " "foo"+-}+data Tag = Tag+    { tagPattern :: Text+      -- ^ In vtags source code this field is named \"pattern\" and EMacs used it as+      --   a regex pattern to locate line with tag. It's looking for ^<tag pattern>.+      --   Looks like vi is not using it.+    , tagName :: Text+      -- ^ text, that editor compare with selected text. So it's really name of entity+    } deriving (Show)++type LineNumber = Int++type ByteOffset = Int++{-| Generate etags for Dhall expressions+-}+generate+    :: Input+    -- ^ Where to look for files. This can be a directory name (@.@ for example),+    --   a file name or `StandardInput`. If `StandardInput`, then this will wait for+    --   file names from @STDIN@.+    --   This way someone can combine tools in @bash@ to send, for example, output from+    --   @find@ to the input of @dhall tags@.+    -> Maybe [Text]+    -- ^ List of suffixes for dhall files or Nothing to check all files+    -> Bool+    -- ^ Flag if `generate` should follow symlinks+    -> IO Text+    -- ^ Content for tags file+generate inp sxs followSyms = do+    files <- inputToFiles followSyms (map T.unpack <$> sxs) inp+    tags <- traverse (\f -> handle (\(SomeException _) -> return mempty)+                                   (fileTags f <$> TIO.readFile f)) files+    return (showTags . mconcat $ tags)++{-| Find tags in Text (second argument) and generates a list of them+    To make tags for filenames that works in both emacs and vi, add two initial tags.+    First for @filename@ for vi and second with @/filename@ for emacs.+    Other tags are working for both.+-}+fileTags :: FilePath -> Text -> Tags+fileTags f t = Tags (M.singleton f+                    (initialMap <> getTagsFromText t))+    where initialViTag = (LO 1 1, Tag "" (T.pack . takeFileName $ f))+          initialEmacsTag = (LO 1 1, Tag "" ("/" <> (T.pack . takeFileName) f))+          initialMap = [initialViTag, initialEmacsTag]++getTagsFromText :: Text -> [(LineOffset, Tag)]+getTagsFromText t = case exprFromText "" t of+    Right expr -> fixPosAndDefinition t (getTagsFromExpr expr)+    _ -> mempty++{-| Used to update tag position and to build tag from term.+    After getTagsFromExpr line and column in line are in @LineColumn@ for each tag.+    And tagPattern is not added.+    Emacs use tag pattern to check if tag is on line. It compares line from start+    with tag pattern and in case they are the same, relocate user.+    fixPosAndDefinition change position to line and byte offset (@LineOffset@) and+    add tag pattern. For example, for Dhall string:++    >>> let dhallSource = "let foo = \"bar\"\nlet baz = \"qux\""++    Input for this function is:++    >>> foundTerms = [(LC 1 4, "foo"), (LC 2 4, "baz")]++    And:++    >>> fixPosAndDefinition dhallSource foundTerms+    [(LO {loLine = 1, loOffset = 5},Tag {tagPattern = "let foo ", tagName = "foo"}),(LO {loLine = 2, loOffset = 21},Tag {tagPattern = "let baz ", tagName = "baz"})]++    where 21 is byte offset from file start.+-}+fixPosAndDefinition :: Text -> [(LineColumn, Text)] -> [(LineOffset, Tag)]+fixPosAndDefinition t = foldMap (\(LC ln c, term) ->+             let (ln', offset, tPattern) = fromMaybe (fallbackInfoForText ln c)+                                                     (infoForText term ln)+             in [(LO ln' offset, Tag tPattern term)])+    where mls :: M.Map Int (Text, Int)+          -- ^ mls is map that for each line has length of file before this map and line content.+          --   In example above, first line is 15 bytes long and '\n', mls contain:+          --   (1, (16, "let foo = "bar"")+          --   That allow us to get byte offset easier.+          mls = M.fromList . fst . foldl' processLine ([], 0) . zip [1..] $ T.lines t++          {-| processLine is a worker for `foldl` that generates the list of lines with+              byte offsets from the start of the first line from a list of lines+          -}+          processLine+              :: ([(LineNumber, (Text, ByteOffset))], ByteOffset)+              -- ^ previous result and byte offset for the start of current line+              -> (LineNumber, Text)+              -> ([(LineNumber, (Text, ByteOffset))], ByteOffset)+              -- ^ next result, where new line was added and byte offset for next line+          processLine (numberedLinesWithSizes, bytesBeforeLine) (n, line) =+              ((n, (line, bytesBeforeLine)): numberedLinesWithSizes, bytesBeforeNextLine)+              where bytesBeforeNextLine = bytesBeforeLine + lengthInBytes line + 1++          lineFromMap ln = fromMaybe ("", 0) (ln `M.lookup` mls)++          lengthInBytes = BS.length . encodeUtf8++          {-| get information about term from map of lines+              In most cases, @LineColumn@ after `getTagsFromExpr` points to byte before term.+              It's better to have term in term pattern, so this function finds and updates+              line number and byte offset and generate pattern.+          -}+          infoForText+              :: Text+              -- ^ term to find+              -> Int+              -- ^ line where to start+              -> Maybe (Int, Int, Text)+              -- ^ (Line number, byte offset, pattern to find term in file)+          infoForText term ln+              | ln <= 0 = Nothing+              | T.null part2 = infoForText term (ln - 1)+              | otherwise = Just (ln, lsl + 1 + lengthInBytes part1, part1 <> termAndNext)+              where (l, lsl) = lineFromMap ln+                    (part1, part2) = T.breakOn term l+                    termAndNext = T.take (T.length term + 1) part2++          fallbackInfoForText ln c = (ln, lsl + 1 + lengthInBytes pat, pat)+              where (l, lsl) = lineFromMap ln+                    pat = T.take c l++getTagsFromExpr :: Expr Src a -> [(LineColumn, Text)]+getTagsFromExpr = go (LC 0 0) []+    where go lpos mts = \case+              (Let b e) -> go lpos (mts <> parseBinding lpos b) e+              (Annot e1 e2) -> go lpos (go lpos mts e1) e2+              (Record mr) -> mts <> tagsFromDhallMap lpos (recordFieldValue <$> mr)+              (RecordLit mr) -> mts <> tagsFromDhallMap lpos (recordFieldValue <$> mr)+              (Union mmr) -> mts <> tagsFromDhallMapMaybe lpos mmr+              (Note s e) -> go (srcToLineColumn s) mts e+              _ -> mts++          tagsFromDhallMap lpos = foldMapWithKey (tagsFromDhallMapElement lpos)++          tagsFromDhallMapMaybe lpos = foldMapWithKey (\k -> \case+              Just e -> tagsFromDhallMapElement lpos k e+              _ -> [(lpos, k)])++          tagsFromDhallMapElement lpos k e = go pos [(pos, k)] e+              where pos = firstPosFromExpr lpos e++          parseBinding :: LineColumn -> Binding Src a -> [(LineColumn, Text)]+          parseBinding lpos b = go p2 [(p0, variable b)] (value b)+              where p0 = posFromBinding (bindingSrc0 b) lpos+                    p1 = posFromBinding (bindingSrc1 b) p0+                    p2 = posFromBinding (bindingSrc2 b) p1+          posFromBinding src startPos = maybe startPos srcToLineColumn src++srcToLineColumn :: Src -> LineColumn+srcToLineColumn s = LC line column+    where ssp = srcStart s+          line = unPos . sourceLine $ ssp+          column = unPos . sourceColumn $ ssp++firstPosFromExpr :: LineColumn -> Expr Src a -> LineColumn+firstPosFromExpr lpos = \case+    (Note s _) -> srcToLineColumn s+    _ -> lpos++showTags :: Tags -> Text+showTags (Tags ts) = T.concat . map (uncurry showFileTags) . M.toList $ ts++showFileTags :: FilePath -> [(LineOffset, Tag)] -> T.Text+showFileTags f ts = "\x0c\n" <> T.pack f <> "," <> (showInt . T.length) cs <> "\n" <> cs+    where cs = T.concat . map (uncurry showPosTag) $ ts++showPosTag :: LineOffset -> Tag -> Text+showPosTag lo tag = def <>"\x7f" <> name <> "\x01" <> showInt line <>+                    "," <> showInt offset <> "\n"+    where line = loLine lo+          offset = loOffset lo+          def = tagPattern tag+          name = tagName tag++showInt :: Int -> Text+showInt = T.pack . show++{-| Generate list of files for a given `Input`+-}+inputToFiles+    :: Bool+    -- ^ If `True`, this function will follow  symbolic links+    -> Maybe [String]+    -- ^ List of suffixes. If `Nothing`, all files will be returned.+    --   This parameter only works when the `Input` is an `InputFile` and point to a directory.+    -> Input+    -> IO [ FilePath ]+    --   List of files.+inputToFiles _ _ StandardInput = lines <$> getContents+inputToFiles followSyms suffixes (InputFile path) = go path+    where go p = do+                   isD <- SD.doesDirectoryExist p+                   isSL <- isSymLink+                   if isD+                     then if isSL && not followSyms+                            then return []+                            else do+                                   -- filter . .. and hidden files .*+                                   contents <- fmap (filter ((/=) '.' . head))+                                                    (SD.getDirectoryContents p)+                                   concat <$> mapM (go . (</>) p) contents+                     else return [p | matchingSuffix || p == path]+               where matchingSuffix = maybe True (any (`isSuffixOf` p)) suffixes+                     isSymLink = SD.pathIsSymbolicLink p
src/Dhall/Tutorial.hs view
@@ -1,2869 +1,2319 @@ {-# OPTIONS_GHC -fno-warn-unused-imports #-}--{-| Dhall is a programming language specialized for configuration files.  This-    module contains a tutorial explaning how to author configuration files using-    this language--}-module Dhall.Tutorial (-    -- * Introduction-    -- $introduction--    -- * Types-    -- $types--    -- * Imports-    -- $imports--    -- * Lists-    -- $lists--    -- * Optional values-    -- $optional0--    -- * Records-    -- $records--    -- * Functions-    -- $functions--    -- * Compiler-    -- $compiler--    -- * Strings-    -- $strings--    -- * Combine-    -- $combine--    -- * Let expressions-    -- $let--    -- * Unions-    -- $unions--    -- * Polymorphic functions-    -- $polymorphic--    -- * Total-    -- $total--    -- * Headers-    -- $headers--    -- * Import integrity-    -- $integrity--    -- * Raw text-    -- $rawText--    -- * Formatting code-    -- $format--    -- * Built-in functions-    -- $builtins--    -- ** Caveats-    -- $caveats--    -- ** Extending the language-    -- $extending--    -- ** Overview-    -- $builtinOverview--    -- ** @Bool@-    -- $bool--    -- *** @(||)@-    -- $or--    -- *** @(&&)@-    -- $and--    -- *** @(==)@-    -- $equal--    -- *** @(!=)@-    -- $unequal--    -- *** @if@\/@then@\/@else@-    -- $ifthenelse--    -- ** @Natural@-    -- $natural--    -- *** @(+)@-    -- $plus--    -- *** @(*)@-    -- $times--    -- *** @Natural/even@-    -- $even--    -- *** @Natural/odd@-    -- $odd--    -- *** @Natural/isZero@-    -- $isZero--    -- *** @Natural/fold@-    -- $naturalFold--    -- *** @Natural/build@-    -- $naturalBuild--    -- ** @Integer@-    -- $integer--    -- ** @Double@-    -- $double--    -- ** @Text@-    -- $text--    -- *** @(++)@-    -- $textAppend--    -- ** @List@-    -- $list--    -- *** @(#)@-    -- $listAppend--    -- *** @List/fold@-    -- $listFold--    -- *** @List/build@-    -- $listBuild--    -- *** @List/length@-    -- $listLength--    -- *** @List/head@-    -- $listHead--    -- *** @List/last@-    -- $listLast--    -- *** @List/indexed@-    -- $listIndexed--    -- *** @List/reverse@-    -- $listReverse--    -- ** @Optional@-    -- $optional1--    -- *** @Optional/fold@-    -- $optionalFold--    -- * Prelude-    -- $prelude--    -- * Conclusion-    -- $conclusion--    -- * Frequently Asked Questions (FAQ)-    -- $faq-    ) where--import Data.Vector (Vector)-import Dhall---- $setup------ >>> :set -XOverloadedStrings---- $introduction------ The simplest way to use Dhall is to ignore the programming language features--- and use it as a strongly typed configuration format.  For example, suppose--- that you create the following configuration file:--- --- > $ cat ./config--- > { foo = 1--- > , bar = [3.0, 4.0, 5.0]--- > }--- --- You can read the above configuration file into Haskell using the following--- code:--- --- > -- example.hs--- > --- > {-# LANGUAGE DeriveGeneric     #-}--- > {-# LANGUAGE OverloadedStrings #-}--- > --- > import Dhall--- > --- > data Example = Example { foo :: Natural, bar :: Vector Double }--- >     deriving (Generic, Show)--- > --- > instance Interpret Example--- > --- > main :: IO ()--- > main = do--- >     x <- input auto "./config"--- >     print (x :: Example)--- --- If you compile and run the above example, the program prints the corresponding--- Haskell record:--- --- > $ ./example--- > Example {foo = 1, bar = [3.0,4.0,5.0]}------ You can also load some types directly into Haskell without having to define a--- record, like this:------ >>> :set -XOverloadedStrings--- >>> input auto "True" :: IO Bool--- True------ The `input` function can decode any value if we specify the value's expected--- `Type`:------ > input--- >     :: Type a  -- Expected type--- >     -> Text    -- Dhall program--- >     -> IO a    -- Decoded expression------ ... and we can either specify an explicit type like `bool`:------ > bool :: Type Bool--- > --- > input bool :: Text -> IO Bool--- >--- > input bool "True" :: IO Bool------ >>> input bool "True"--- True------ ... or we can use `auto` to let the compiler infer what type to decode from--- the expected return type:------ > auto :: Interpret a => Type a--- >--- > input auto :: Interpret a => Text -> IO a------ >>> input auto "True" :: IO Bool--- True------ You can see what types `auto` supports \"out-of-the-box\" by browsing the--- instances for the `Interpret` class.  For example, the following instance--- says that we can directly decode any Dhall expression that evaluates to a--- @Bool@ into a Haskell `Bool`:------ > instance Interpret Bool------ ... which is why we could directly decode the string @\"True\"@ into the--- value `True`.------ There is also another instance that says that if we can decode a value of--- type @a@, then we can also decode a @List@ of values as a `Vector` of @a@s:------ > instance Interpret a => Interpret (Vector a)------ Therefore, since we can decode a @Bool@, we must also be able to decode a--- @List@ of @Bool@s, like this:------ >>> input auto "[True, False]" :: IO (Vector Bool)--- [True,False]------ We could also specify what type to decode by providing an explicit `Type`--- instead of using `auto` with a type annotation:------ >>> input (vector bool) "[True, False]"--- [True,False]------ __Exercise:__ Create a @./config@ file that the following program can decode:------ > {-# LANGUAGE DeriveGeneric     #-}--- > {-# LANGUAGE OverloadedStrings #-}--- > --- > import Dhall--- > --- > data Person = Person { age :: Natural, name :: Text }--- >     deriving (Generic, Show)--- > --- > instance Interpret Person--- > --- > main :: IO ()--- > main = do--- >     x <- input auto "./config"--- >     print (x :: Person)------ __Exercise:__ Create a @./config@ file that the following program can decode:------ > {-# LANGUAGE OverloadedStrings #-}--- > --- > import Data.Functor.Identity--- > import Dhall--- > --- > instance Interpret a => Interpret (Identity a)--- > --- > main :: IO ()--- > main = do--- >     x <- input auto "./config"--- >     print (x :: Identity Double)---- $types------ Suppose that we try to decode a value of the wrong type, like this:------ >>> input auto "1" :: IO Bool--- *** Exception:--- ...Error...: Expression doesn't match annotation--- ...--- - Bool--- + Natural--- ...--- 1: 1 : Bool--- ...--- (input):1:1--- ...------ The interpreter complains because the string @\"1\"@ cannot be decoded into a--- Haskell value of type `Bool`.  This part of the type error:------ > - Bool--- > + Natural------ ... means that the expected type was @Bool@ but the inferred type of the--- expression @1@ was @Natural@.------ The code excerpt from the above error message has two components:------ * the expression being type checked (i.e. @1@)--- * the expression's expected type (i.e. @Bool@)------ > Expression--- > ⇩--- > 1 : Bool--- >     ⇧--- >     Expected type------ The @(:)@ symbol is how Dhall annotates values with their expected types.--- This notation is equivalent to type annotations in Haskell using the @(::)@--- symbol.  Whenever you see:------ > x : t------ ... you should read that as \"we expect the expression @x@ to have type--- @t@\". However, we might be wrong and if our expected type does not match the--- expression's actual type then the type checker will complain.------ In this case, the expression @1@ does not have type @Bool@ so type checking--- fails with an exception.------ __Exercise:__ Load the Dhall library into @ghci@ and run these commands to get--- get a more detailed error message:------ > >>> import Dhall--- > >>> :set -XOverloadedStrings--- > >>> detailed (input auto "1") :: IO Bool--- > ...------ ... then read the entire error message------ __Exercise:__ Fix the type error, either by changing the value to decode or--- changing the expected type---- $imports------ You might wonder why in some cases we can decode a configuration file:------ >>> writeFile "bool" "True"--- >>> input auto "./bool" :: IO Bool--- True------ ... and in other cases we can decode a value directly:------ >>> input auto "True" :: IO Bool--- True------ This is because importing a configuration from a file is a special case of a--- more general language feature: Dhall expressions can reference other--- expressions by their file path.------ To illustrate this, let's create three files:--- --- > $ echo "True"  > bool1--- > $ echo "False" > bool2--- > $ echo "./bool1 && ./bool2" > both------ ... and read in all three files in a single expression:--- --- >>> input auto "[ ./bool1 , ./bool2 , ./both ]" :: IO (Vector Bool)--- [True,False,False]------ Each file path is replaced with the Dhall expression contained within that--- file.  If that file contains references to other files then those references--- are transitively resolved.------ In other words: configuration files can reference other configuration files,--- either by their relative or absolute paths.  This means that we can split a--- configuration file into multiple files, like this:------ > $ cat > ./config <<EOF--- > { foo = 1--- > , bar = ./bar--- > }--- > EOF------ > $ echo "[3.0, 4.0, 5.0]" > ./bar------ > $ ./example--- > Example {foo = 1, bar = [3.0,4.0,5.0]}------ However, the Dhall language will forbid cycles in these file references.  For--- example, if we create the following cycle:------ > $ echo './file1' > file2--- > $ echo './file2' > file1------ ... then the interpreter will reject the import:------ >>> input auto "./file1" :: IO Natural--- *** Exception: --- ↳ ./file1---   ↳ ./file2--- ...--- Cyclic import: ./file1--- ...------ You can also import expressions by URL.  For example, you can find a Dhall--- expression hosted at this GitHub URL:------ <https://raw.githubusercontent.com/dhall-lang/dhall-haskell/18e4e9a18dc53271146df3ccf5b4177c3552236b/examples/True>------ > $ curl https://raw.githubusercontent.com/dhall-lang/dhall-haskell/18e4e9a18dc53271146df3ccf5b4177c3552236b/examples/True--- > True------ ... and you can reference that expression either directly:------ >>> input auto "https://raw.githubusercontent.com/dhall-lang/dhall-haskell/18e4e9a18dc53271146df3ccf5b4177c3552236b/examples/True" :: IO Bool--- True--- --- ... or inside of a larger expression:------ >>> input auto "False == https://raw.githubusercontent.com/dhall-lang/dhall-haskell/18e4e9a18dc53271146df3ccf5b4177c3552236b/examples/True" :: IO Bool--- False------ 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,--- as a pastebin, or your own web server.------ You can also import Dhall expressions from environment variables, too:------ >>> System.Environment.setEnv "FOO" "1"--- >>> input auto "env:FOO" :: IO Natural--- 1------ You can import types, too.  For example, we can change our @./bar@ file to:------ > $ echo "[3.0, 4.0, 5.0] : List ./type" > ./bar------ ... then specify the @./type@ in a separate file:------ > $ echo "Double" > ./type------ ... and everything still type checks:------ > $ ./example--- > Example {foo = 1, bar = [3.0,4.0,5.0]}------ Note that all imports must be terminated by whitespace or you will get either--- an import error or a parse error, like this:------ >>> writeFile "baz" "2.0"--- >>> input auto "./baz: Double" :: IO Double--- *** Exception: --- ↳ ./baz: --- ...--- ...Error...: Missing file ...baz:--- ...------ This is because the parser thinks that @./baz:@ is a single token due to--- the missing whitespace before the colon and tries to import a file named--- @./baz:@, which does not exist.  To fix the problem we have to add a space--- after @./baz@:------ >>> input auto "./baz : Double" :: IO Double--- 2.0------ __Exercise:__ There is a @not@ function hosted online here:------ <https://raw.githubusercontent.com/dhall-lang/Prelude/35deff0d41f2bf86c42089c6ca16665537f54d75/Bool/not>------ Visit that link and read the documentation.  Then try to guess what this--- code returns:------ > >>> input auto "https://raw.githubusercontent.com/dhall-lang/Prelude/35deff0d41f2bf86c42089c6ca16665537f54d75/Bool/not https://raw.githubusercontent.com/dhall-lang/dhall-haskell/18e4e9a18dc53271146df3ccf5b4177c3552236b/examples/True" :: IO Bool--- > ???------ Run the code to test your guess---- $lists------ You can store 0 or more values of the same type in a list, like this:------ > [1, 2, 3]------ Every list can be followed by the type of the list.  The type annotation is--- required for empty lists but optional for non-empty lists.  You will get a--- type 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--- ...--- 1: []--- ...--- (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:------ >>> input auto "[1, True, 3]" :: IO (Vector Natural)--- *** Exception:--- ...Error...: List elements should all have the same type--- ...--- - Natural--- + Bool--- ...--- 1:     True--- ...--- (input):1:5--- ...------ __Exercise:__ What is the shortest @./config@ file that you can decode using--- this command:------ > >>> input auto "./config" :: IO (Vector (Vector Natural))---- $optional0------ @Optional@ values are either of the form @Some aValue@ or @None aType@.------ For example, these are valid @Optional@ values:------ > Some 1--- >--- > None Natural------ ... which both have type @Optional Natural@------ An @Optional@ corresponds to Haskell's `Maybe` type for decoding purposes:------ >>> input auto "Some 1" :: IO (Maybe Natural)--- Just 1--- >>> input auto "None Natural" :: IO (Maybe Natural)--- Nothing------ __Exercise:__ Author a @./config@ file that you can decode like this:------ > >>> input auto "./config" :: IO (Maybe (Maybe (Maybe Natural)))--- > ???---- $records------ Record literals are delimited by curly braces and their fields are separated--- by commas.  For example, this is a valid record literal:------ > { foo = True--- > , bar = 2--- > , baz = 4.2--- > }------ A record type is like a record literal except instead of specifying each--- field's value we specify each field's type.  For example, the preceding--- record literal has the following record type:------ > { foo : Bool--- > , bar : Natural--- > , baz : Double--- > }------ If you want to specify an empty record literal, you must use @{=}@, which is--- special syntax reserved for empty records.  If you want to specify the empty--- record type, then you use @{}@.  If you forget which is which you can always--- ask the @dhall@ compiler to remind you of the type for each one:------ > $ dhall--- > {=}--- > <Ctrl-D>--- > {}--- > --- > {=}------ > $ dhall--- > {}--- > <Ctrl-D>--- > Type--- > --- > {}------ You can access a field of a record using the following syntax:------ > record.fieldName------ ... which means to access the value of the field named @fieldName@ from the--- @record@.  For example:------ >>> input auto "{ foo = True, bar = 2, baz = 4.2 }.baz" :: IO Double--- 4.2------ ... and you can project out multiple fields into a new record using this--- syntax:------ > someRecord.{ field₀, field₁, … }------ For example:------ > $ dhall--- > { x = 1, y = True, z = "ABC" }.{ x, y }--- > <Ctrl-D>--- > { x : Natural, y : Bool }--- > --- > { x = 1, y = True }------ __Exercise__: What is the type of this record:------ > { foo = 1--- > , bar =--- >     { baz = 2.0--- >     , qux = True--- >     }--- > }------ __Exercise__: Save the above code to a file named @./record@ and then try to--- access the value of the @baz@ field---- $functions------ The Dhall programming language also supports user-defined anonymous--- functions.  For example, we can save the following anonymous function to a--- file:------ > $ cat > makeBools--- > \(n : Bool) ->--- >     [ n && True, n && False, n || True, n || False ]--- > <Ctrl-D>------ ... or we can use Dhall's support for Unicode characters to use @λ@ (U+03BB)--- instead of @\\@ and @→@ (U+2192) instead of @->@ (for people who are into that--- sort of thing):------ > $ cat > makeBools--- > λ(n : Bool) →--- >     [ n && True, n && False, n || True, n || False ]--- > <Ctrl-D>------ You can read this as a function of one argument named @n@ that has type--- @Bool@.  This function returns a @List@ of @Bool@s.  Each element of the--- @List@ depends on the input argument named @n@.------ The (ASCII) syntax for anonymous functions resembles the syntax for anonymous--- functions in Haskell.  The only difference is that Dhall requires you to--- annotate the type of the function's input.------ You can import this function into Haskell, too:------ >>> makeBools <- input auto "./makeBools" :: IO (Bool -> Vector Bool)--- >>> makeBools True--- [True,False,True,True]------ The reason this works is that there is an `Interpret` instance for simple--- functions:------ > instance (Inject a, Interpret b) => Interpret (a -> b)------ Thanks to currying, this instance works for functions of multiple simple--- arguments:------ >>> dhallAnd <- input auto "λ(x : Bool) → λ(y : Bool) → x && y" :: IO (Bool -> Bool -> Bool)--- >>> dhallAnd True False--- False------ However, you can't convert anything more complex than that (like a polymorphic--- or higher-order function).  You will need to apply those functions to their--- arguments within Dhall before converting their result to a Haskell value.------ Just like `Interpret`, you can derive `Inject` for user-defined data types:------ > {-# LANGUAGE DeriveAnyClass    #-}--- > {-# LANGUAGE DeriveGeneric     #-}--- > {-# LANGUAGE OverloadedStrings #-}--- > --- > module Main where--- > --- > import Dhall--- > --- > data Example0 = Example0 { foo :: Bool, bar :: Bool }--- >     deriving (Generic, Inject)--- > --- > main = do--- >     f <- input auto "λ(r : { foo : Bool, bar : Bool }) → r.foo && r.bar"--- >     print (f (Example0 { foo = True, bar = False }) :: Bool)--- >     print (f (Example0 { foo = True, bar = True  }) :: Bool)------ The above program prints:------ > False--- > True---- $compiler------ We can also test our @makeBools@ function directly from the command line.--- This library comes with a command-line executable program named @dhall@ that--- you can use to both type-check files and convert them to a normal form.  Our--- compiler takes a program on standard input and then prints the program's type--- to standard error followed by the program's normal form to standard output:------ > $ dhall--- > ./makeBools--- > <Ctrl-D>--- > ∀(n : Bool) → List Bool--- > --- > λ(n : Bool) → [ n, False, True, n ]------ The first line says that @makeBools@ is a function of one argument named @n@--- that has type @Bool@ and the function returns a @List@ of @Bool@s.  The @∀@--- (U+2200) symbol is shorthand for the ASCII @forall@ keyword:------ > ∀(x : a) → b        -- This type ...--- > --- > forall (x : a) → b  -- ... is the same as this type------ ... and Dhall's @forall@ keyword behaves the same way as Haskell's @forall@--- keyword for input values that are @Type@s:------ > forall (x : Type) → b  -- This Dhall type ...--- --- > forall x . b           -- ... is the same as this Haskell type------ The part where Dhall differs from Haskell is that you can also use--- @∀@/@forall@ to give names to non-@Type@ arguments (such as the first--- argument to @makeBools@).------ The second line of Dhall's output is our program's normal form:------ > λ(n : Bool) → [ n, False, True, n ]------ ... and the interpreter was able to simplify our expression by noting that:------ * @n && True  = n@--- * @n && False = False@--- * @n || True  = True@--- * @n || False = n@------ To apply a function to an argument you separate the function and argument by--- whitespace (just like Haskell):------ @f x@------ You can read the above as \"apply the function @f@ to the argument @x@\".  This--- means that we can \"apply\" our @./makeBools@ function to a @Bool@ argument--- like this:------ > $ dhall--- > ./makeBools True--- > <Ctrl-D>--- > List Bool--- > --- > [True, False, True, True]------ Remember that file paths are synonymous with their contents, so the above--- code is exactly equivalent to:--- --- > $ dhall--- > (λ(n : Bool) → [n && True, n && False, n || True, n || False]) True--- > <Ctrl-D>--- > List Bool--- > --- > [True, False, True, True]------ When you apply an anonymous function to an argument, you substitute the--- \"bound variable" with the function's argument:------ >    Bound variable--- >    ⇩--- > (λ(n : Bool) → ...) True--- >                     ⇧--- >                     Function argument------ So in our above example, we would replace all occurrences of @n@ with @True@,--- like this:------ > -- If we replace all of these `n`s with `True` ...--- > [n && True, n && False, n || True, n || False]--- >--- > -- ... then we get this:--- > [True && True, True && False, True || True, True || False]--- >--- > -- ... which reduces to the following normal form:--- > [True, False, True, True]------ Now that we've verified that our function type checks and works, we can use--- the same function within Haskell:------ >>> input auto "./makeBools True" :: IO (Vector Bool)--- [True,False,True,True]------ __Exercise__: Create a file named @getFoo@ that is a function of the following--- type:------ > ∀(r : { foo : Bool, bar : Text }) → Bool------ This function should take a single input argument named @r@ that is a record--- with two fields.  The function should return the value of the @foo@ field.------ __Exercise__: Use the @dhall@ compiler to infer the type of the function you--- just created and verify that your function has the correct type------ __Exercise__: Use the @dhall@ compiler to apply your function to a sample--- record---- $strings--- Dhall supports ordinary string literals with Haskell-style escaping rules:------ > dhall--- > "Hello, \"world\"!"--- > <Ctrl-D>--- > Text--- >--- > "Hello, \"world\"!"------ ... and Dhall also supports Nix-style multi-line string literals:------ > dhall--- > ''--- >     #!/bin/bash--- >     --- >     echo "Hi!"--- > ''--- > <Ctrl-D>--- > Text--- >--- > "\n#!/bin/bash\n\necho \"Hi!\"\n"------ These \"double single quote strings\" ignore all special characters, with one--- exception: if you want to include a @''@ in the string, you will need to--- escape it with a preceding @'@ (i.e. use @'''@ to insert @''@ into the final--- string).------ These strings also strip leading whitespace using the same rules as Nix.--- Specifically: \"it strips from each line a number of spaces equal to the--- minimal indentation of the string as a whole (disregarding the indentation--- of empty lines).\"------ You can also interpolate expressions into strings using @${...}@ syntax.  For--- example:------ > $ dhall--- >     let name = "John Doe"--- > in  let age  = 21--- > in  "My name is ${name} and my age is ${Natural/show age}"--- > <Ctrl-D>--- > Text--- >--- > "My name is John Doe and my age is 21"------ Note that you can only interpolate expressions of type @Text@------ If you need to insert a @"${"@ into a string without interpolation then use--- @"''${"@ (same as Nix)------ > ''--- >     for file in *; do--- >       echo "Found ''${file}"--- >     done--- > ''---- $combine------ You can combine two records, using either the @(//)@ operator or the--- @(/\\)@ operator.------ The @(//)@ operator (or @(⫽)@ U+2AFD) combines the fields of both records,--- preferring fields from the right record if they share fields in common:------ > $ dhall--- > { foo = 1, bar = "ABC" } // { baz = True }--- > <Ctrl-D>--- > { bar : Text, baz : Bool, foo : Natural }--- > --- > { bar = "ABC", baz = True, foo = 1 }--- > $ dhall--- > { foo = 1, bar = "ABC" } ⫽ { bar = True }  -- Fancy unicode--- > <Ctrl-D>--- > { bar : Bool, foo : Natural }--- > --- > { bar = True, foo = 1 }------ Note that the order of record fields does not matter.  The compiler--- automatically sorts the fields.------ The @(/\\)@ operator (or @(∧)@ U+2227) also lets you combine records, but--- behaves differently if the records share fields in common.  The operator--- combines shared fields recursively if they are both records:------ > $ dhall--- > { foo = { bar = True }, baz = "ABC" } /\ { foo = { qux = 1.0 } }--- > <Ctrl-D>--- > { baz : Text, foo : { bar : Bool, qux : Double } }--- > --- > { baz = "ABC", foo = { bar = True, qux = 1.0 } }------ ... but fails with a type error if either shared field is not a record:------ > $ dhall--- > { foo = 1, bar = "ABC" } ∧ { foo = True }--- > <Ctrl-D>--- > Use "dhall --explain" for detailed errors--- > --- > Error: Field collision--- > --- > { foo = 1, bar = "ABC" } ∧ { foo = True }--- > --- > (stdin):1:1------ __Exercise__: Combine any record with the empty record.  What do you expect--- to happen?------ You can analogously combine record types using the @//\\\\@ operator (or @(⩓)@ U+2A53):------ > $ dhall--- > { foo : Natural } ⩓ { bar : Text }--- > <Ctrl-D>--- > { foo : Natural, bar : Text }------ ... which behaves the exact same, except at the type level, meaning that the--- operator descends recursively into record types:------ > $ dhall--- > { foo : { bar : Text } } ⩓ { foo : { baz : Bool }, qux : Natural }--- > <Ctrl-D>--- > { foo : { bar : Text, baz : Bool }, qux : Natural }---- $let------ Dhall also supports @let@ expressions, which you can use to define--- intermediate values in the course of a computation, like this:------ > $ dhall--- > let x = "ha" in x ++ x--- > <Ctrl-D>--- > Text--- >--- > "haha"------ You can also annotate the types of values defined within a @let@ expression,--- like this:------ > $ dhall--- > let x : Text = "ha" in x ++ x--- > <Ctrl-D>--- > Text--- >--- > "haha"------ You need to nest @let@ expressions if you want to define more than one value--- in this way:------ > $ dhall--- >     let x = "Hello, "--- > in  let y = "world!"--- > in  x ++ y--- > <Ctrl-D>--- > Text--- > --- > "Hello, world!"------ Dhall is whitespace-insensitive, so feel free to format things over multiple--- lines or indent in any way that you please.------ If you want to define a named function, just give a name to an anonymous--- function:------ > $ dhall--- > let twice = λ(x : Text) → x ++ x in twice "ha"--- > <Ctrl-D>--- > Text--- > --- > "haha"------ Unlike Haskell, Dhall does not support function arguments on the left-hand--- side of the equals sign, so this will not work:------ > $ dhall--- > let twice (x : Text) = x ++ x in twice "ha"--- > <Ctrl-D>--- > Error: Invalid input--- > --- > (stdin):1:11:--- >   |--- > 1 | let twice (x : Text) = x ++ x in twice "ha"--- >   |           ^--- > unexpected '('--- > expecting ':', '=', or the rest of label------ The error message says that Dhall expected either a @(:)@ (i.e. the beginning--- of a type annotation) or a @(=)@ (the beginning of the assignment) and not a--- function argument.------ You can also use @let@ expressions to rename imports, like this:------ > $ dhall--- > let not = https://raw.githubusercontent.com/dhall-lang/Prelude/35deff0d41f2bf86c42089c6ca16665537f54d75/Bool/not--- > in  not True--- > <Ctrl-D>--- > Bool--- > --- > False------ ... or to define synonyms for types:------ > $ dhall <<< 'let Name : Type = Text in [ "John", "Mary" ] : List Name'--- > List Text--- > --- > [ "John", "Mary" ]------ __Exercise:__ What do you think the following code will normalize to?------ >     let x = 1--- > in  let x = 2--- > in  x------ Test your guess using the @dhall@ compiler------ __Exercise:__ Now try to guess what this code will normalize to:------ >     let x = "ha"--- > in  let x = x ++ "ha"--- > in  x------ __Exercise:__ What about this code?------ > let x = x ++ "ha"--- > in  x---- $unions------ A union is a value that can be one of many alternative types of values.  For--- example, the following union type:------ > < Left : Natural | Right : Bool >------ ... represents a value that can be either a @Natural@ or a @Bool@ value.  If--- you are familiar with Haskell these are exactly analogous to Haskell's--- \"sum types\".------ Each alternative is associated with a tag that distinguishes that alternative--- from other alternatives.  In the above example, the @Left@ tag is used for--- the @Natural@ alternative and the @Right@ tag is used for the @Bool@--- alternative.------ You can specify the value of a union constructor like this:------ > let Union = < Left : Natural | Right : Bool>--- > --- > [ Union.Left 0, Union.Right True ] : List Union------ In other words, you can access a union constructor as a field of a union--- type and use that constructor to wrap a value of a type appropriate for--- that alternative.  In the above example, the @Left@ constructor can wrap--- a @Natural@ value and the @Right@ constructor can wrap a @Bool@ value.  We--- can also confirm that by inspecting their type:------ > $ echo '< Left : Natural | Right : Bool>' > ./Union------ > $ dhall --annotate <<< '(./Union).Left'--- >   < Left : Natural | Right : Bool >.Left--- > : ∀(Left : Natural) → < Left : Natural | Right : Bool >------ > $ dhall --annotate <<< '(./Union).Right'--- >   < Left : Natural | Right : Bool >.Right--- > : ∀(Right : Bool) → < Left : Natural | Right : Bool >------ In other words, the @Left@ constructor is a function from a @Natural@ to a--- value of our @Union@ type and the @Right@ constructor is a separate function--- from a @Bool@ to that same @Union@ type.------ You can consume a union using the built-in @merge@ function.  For example,--- suppose we want to convert our union to a @Bool@ but we want to behave--- differently depending on whether or not the union is a @Natural@ wrapped in--- the @Left@ constructor or a @Bool@ wrapped in the @Right@ constructor .  We--- would write:------ > $ cat > process <<EOF--- >     λ(union : < Left : Natural | Right : Bool >)--- > →   let handlers =--- >             { Left  = Natural/even  -- Natural/even is a built-in function--- >             , Right = λ(b : Bool) → b--- >             }--- > in  merge handlers union : Bool--- > EOF------ Now our @./process@ function can handle both alternatives:------ > $ dhall <<< './process ((./Union).Left 3)'--- > False------ > $ dhall <<< './process ((./Union).Right True)'--- > True------ Every @merge@ has the following form:------ > merge handlers union : type------ ... where: ------ * @union@ is the union you want to consume--- * @handlers@ is a record with one function per alternative of the union--- * @type@ is the declared result type of the @merge@------ The @merge@ function selects which function to apply from the record based on--- which alternative the union selects:------ > merge { Foo = f, ... } (< … >.Foo x) = f x------ So, for example:------ > merge { Left = Natural/even, Right = λ(b : Bool) → b } (< Left : Natural | Right : Bool >.Left 3)--- >     = Natural/even 3--- >     = False------ ... and similarly:------ > merge { Left = Natural/even, Right = λ(b : Bool) → b } (< Left : Natural | Right : Bool >.Right True)--- >     = (λ(b : Bool) → b) True--- >     = True------ Notice that each handler has to return the same type of result (@Bool@ in--- this case).------ You can also store more than one value within alternatives using Dhall's--- support for anonymous records.  You can nest an anonymous record within a--- union such as in this type:------ > < Empty : {} | Person : { name : Text, age : Natural } >------ You can even go a step further and omit the type of an alternative if it--- stores no data, like this:------ > < Empty | Person : { name : Text, age : Natural } >--------- This union of records resembles following equivalent Haskell data type:------ > data Example = Empty | Person { name :: Text, age :: Text }------ Empty alternatives like @Empty@ require no argument:------ > let MyType = < Empty | Person : { name : Text, age : Natural } >--- > --- > in  [   MyType.Empty  -- Note the absence of any argument to `Empty`--- >     ,   MyType.Person { name = "John", age = 23 }--- >     ,   MyType.Person { name = "Amy" , age = 25 }--- >     ]------ ... 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 `λ`--- >--- >     ,   Person =--- >             λ(person : { name : Text, age : Natural })--- >         →   "Name: ${person.name}, Age: ${Natural/show person.age}"--- >     }--- >     x------ __Exercise__: Create a list of the following type with at least one element--- per alternative:------ > List < Left : Natural | Right : Double >---- $polymorphic------ The Dhall language supports defining polymorphic functions (a.k.a.--- \"generic\" functions) that work on more than one type of value.  However,--- Dhall differs from Haskell by not inferring the types of these polymorphic--- functions.  Instead, you must be explicit about what type of value the--- function is specialized to.------ Take, for example, Haskell's identity function named @id@:------ > id :: a -> a--- > id = \x -> x------ The identity function is polymorphic, meaning that `id` works on values of--- different types:------ >>> id 4--- 4--- >>> id True--- True------ The equivalent function in Dhall is:------ > λ(a : Type) → λ(x : a) → x------ Notice how this function takes two arguments instead of one.  The first--- argument is the type of the second argument.------ Let's illustrate how this works by actually using the above function:------ > $ echo "λ(a : Type) → λ(x : a) → x" > id------ If we supply the function alone to the compiler we get the inferred type as--- the first line:--- --- > $ dhall--- > ./id--- > <Ctrl-D>--- > ∀(a : Type) → ∀(x : a) → a--- > --- > λ(a : Type) → λ(x : a) → x------ You can read the type @(∀(a : Type) → ∀(x : a) → a)@ as saying: \"This is the--- type of a function whose first argument is named @a@ and is a @Type@.  The--- second argument is named @x@ and has type @a@ (i.e. the value of the first--- argument).  The result also has type @a@.\"------ This means that the type of the second argument changes depending on what--- type we provide for the first argument.  When we apply @./id@ to @Natural@,--- we create a function that expects an @Natural@ argument:------ > $ dhall--- > ./id Natural--- > <Ctrl-D>--- > ∀(x : Natural) → Natural--- > --- > λ(x : Natural) → x------ Similarly, when we apply @./id@ to @Bool@, we create a function that expects a--- @Bool@ argument:------ > $ dhall--- > ./id Bool--- > <Ctrl-D>--- > ∀(x : Bool) → Bool--- > --- > λ(x : Bool) → x------ We can then supply the final argument to each of those functions to show--- that they both work on their respective types:------ > $ dhall--- > ./id Natural 4--- > <Ctrl-D>--- > Natural--- > --- > 4------ > $ dhall--- > ./id Bool True--- > <Ctrl-D>--- > Bool--- > --- > True------ Built-in functions can also be polymorphic, too.  For example, we can ask--- the compiler for the type of @List/reverse@, the function that reverses a--- list:------ > $ dhall--- > List/reverse--- > <Ctrl-D>--- > ∀(a : Type) → List a → List a--- > --- > List/reverse------ The first argument to @List/reverse@ is the type of the list to reverse:------ > $ dhall--- > List/reverse Bool--- > <Ctrl-D>--- > List Bool → List Bool--- > --- > List/reverse Bool------ ... and the second argument is the list to reverse:------ > $ dhall--- > List/reverse Bool [True, False]--- > <Ctrl-D>--- > List Bool--- > --- > [False, True] : List Bool------ Note that the second argument has no name.  This type:------ > ∀(a : Type) → List a → List a------ ... is equivalent to this type:------ > ∀(a : Type) → ∀(_ : List a) → List a------ In other words, if you don't see the @∀@ symbol surrounding a function--- argument type then that means that the name of the argument is @"_"@.  This--- is true even for user-defined functions:------ > $ dhall--- > λ(_ : Text) → 1--- > <Ctrl-D>--- > Text → Natural--- > --- > λ(_ : Text) → 1------ The type @(Text → Natural)@ is the same as @(∀(_ : Text) → Natural)@------ __Exercise__ : Translate Haskell's `flip` function to Dhall---- $total------ Dhall is a total programming language, which means that Dhall is not--- Turing-complete and evaluation of every Dhall program is guaranteed to--- eventually halt.  There is no upper bound on how long the program might take--- to evaluate, but the program is guaranteed to terminate in a finite amount of--- time and not hang forever.------ This guarantees that all Dhall programs can be safely reduced to a normal--- form where as many functions have been evaluated as possible.  In fact, Dhall--- expressions can be evaluated even if all function arguments haven't been fully--- applied.  For example, the following program is an anonymous function:------ > $ dhall--- > \(n : Bool) -> 10 * 10--- > <Ctrl-D>--- > ∀(n : Bool) → Natural--- > --- > λ(n : Bool) → 100------ ... and even though the function is still missing the first argument named--- @n@ the compiler is smart enough to evaluate the body of the anonymous--- function ahead of time before the function has even been invoked.------ We can use the @map@ function from the Prelude to illustrate an even more--- complex example:------ > $ dhall--- >     let Prelude/List/map = https://raw.githubusercontent.com/dhall-lang/Prelude/35deff0d41f2bf86c42089c6ca16665537f54d75/List/map--- > in  λ(f : Natural → Natural) → Prelude/List/map Natural Natural f [1, 2, 3]--- > <Ctrl-D>--- > ∀(f : Natural → Natural) → List Natural--- > --- > λ(f : Natural → Natural) → [f 1, f 2, f 3] : List Natural------ Dhall can apply our function to each element of the list even before we specify--- which function to apply.------ The language will also never crash or throw any exceptions.  Every--- computation will succeed and produce something, even if the result might be--- an @Optional@ value:------ > $ dhall--- > List/head Natural ([] : List Natural)--- > <Ctrl-D>--- > Optional Natural--- > --- > None Natural------ __Exercise__: The Dhall Prelude provides a @replicate@ function which you can--- find here:------ <https://raw.githubusercontent.com/dhall-lang/Prelude/35deff0d41f2bf86c42089c6ca16665537f54d75/List/replicate>------ Test what the following Dhall expression normalizes to:------ > let replicate = https://raw.githubusercontent.com/dhall-lang/Prelude/35deff0d41f2bf86c42089c6ca16665537f54d75/List/replicate--- > in  replicate 10------ __Exercise__: If you have a lot of spare time, try to \"break the compiler\" by--- finding an input expression that crashes or loops forever (and file a bug--- report if you succeed)---- $headers------ Sometimes you would like to provide additional request headers when importing--- Dhall expressions from URLs.  For example, you might want to provide an--- authorization header or specify the expected content type.------ Dhall URL imports let you add or modify request headers with the @using@--- keyword:------ > https://example.com/example.dhall using ./headers------ ... where you can replace @./headers@ with any import that points to a Dhall--- expression of the following type:------ > List { header : Text, value : Text }------ For example, if you needed to specify the content type correctly in order to--- download the file, then your @./headers@ file might look like this:------ > $ cat headers--- > [ { header = "Accept", value = "application/dhall" } ]------ ... or if you needed to provide an authorization token to access a private--- GitHub repository, then your headers could look like this:------ > [ { header = "Authorization", value = "token ${env:GITHUB_TOKEN as Text}" } ]------ This would read your GitHub API token from the @GITHUB_TOKEN@ environment--- variable and supply that token in the authorization header.------ You cannot inline the headers within the same file as the URL.  You must--- provide them as a separate import.  That means that this is /not/ legal code:------ > http://example.com/example.dhall using [ { header = "Accept", value = "application/dhall" } ]  -- NOT legal------ Dhall will forward imports if you import an expression from a URL that--- contains a relative import.  For example, if you import an expression like--- this:--- --- > http://example.com/example.dhall using ./headers--- --- ... and @http:\/\/example.com/example.dhall@ contains a relative import of @./foo@--- then Dhall will import @http:\/\/example.com/foo@ using the same @./headers@ file.---- $integrity------ Sometimes you want to use share code while still ensuring that the imported--- value never changes and can't be corrupted by a malicious attacker.  Dhall--- provides built-in support for hashing imported values to verify that their--- value never changes------ For example, suppose you save the following two files:------ > $ cat ./foo--- > ./bar sha256:6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b------ > $ cat ./bar--- > ./baz------ > $ cat ./baz--- > 1------ The first file named @./foo@ contains an example of an integrity check.  You--- can add @sha256:XXX@ after any import (such as after @./bar@), where @XXX@ is--- an expected 64-character @sha256@ hash of the Dhall value.  To be precise,--- the hash represents a @sha256@ hash of the UTF-8 encoding of a canonical text--- representation of the fully resolved and normalized abstract syntax tree of--- the imported expression.------ Dhall will verify that the expected hash matches the actual hash of the--- imported Dhall value and reject the import if there is a hash mismatch:------ > $ dhall <<< './foo'--- > Natural--- > --- > 1------ This implies that the hash only changes if the Dhall value changes.  For--- example, if you add a comment to the @./bar@ file:------ > $ cat ./bar--- > -- This comment does not change the hash--- > ./baz------ ... then @./foo@ will still successfully import @./bar@ because the hash--- only depends on the normalized value and does not depend on meaningless--- changes to whitespace or comments:------ > $ dhall <<< './foo'  # This still succeeds--- > Natural--- > --- > 1------ You can compute the Hash for any import by using the hash subcommand --- of this package.  For example:------ > dhall hash <<< './bar'--- > sha256:6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b------ Then you can paste that output into your code after the import------ Now suppose that you you change the value of the @./baz@ file:------ > $ cat ./baz--- > 2------ ... then the @./foo@ file will fail to import @./bar@, even though the--- text of the @./bar@ file technically never changed:------ > dhall <<< './foo'--- > --- > Error: Import integrity check failed--- > --- > Expected hash:--- > --- > ↳ 6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b--- > --- > Actual hash:--- > --- > ↳ d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35------ This is because the @./bar@ file now represents a new value (@2@ instead of--- @1@), even though the text of the @./bar@ is still the same.  Since the value--- changed the hash must change as well.  However, we could change @./baz@ to:------ > $ cat baz--- > if True then 1 else 2------ ... and the import would succeed again because the final result is still @1@.------ The integrity hash ensures that your import's final meaning can never change,--- so an attacker can never compromise an imported value protected by a hash--- unless they can break SHA-256 encryption.  The hash not only protects the--- file that you immediately import, but also protects every transitive import--- as well.------ You can also safely refactor your imported dependencies knowing that the--- refactor will not change your hash so long as your refactor is--- behavior-preserving.  This provides an easy way to detect refactoring errors--- that you might accidentally introduce.  The hash not only protects you--- from attackers, but also protects against human error, too!------ If you have a file which either doesn't already use hashed imports,--- or you changed some of the imports and want to update the hashes you can use the--- freeze command to either add or update hashes:------ > $ cat foo.dhall--- > let replicate =--- >       https://raw.githubusercontent.com/dhall-lang/Prelude/c79c2bc3c46f129cc5b6d594ce298a381bcae92c/List/replicate--- > in  replicate 5--- > $--- > $ dhall freeze --inplace ./foo.dhall--- > $ cat ./foo.dhall--- > let replicate =--- >       https://raw.githubusercontent.com/dhall-lang/Prelude/c79c2bc3c46f129cc5b6d594ce298a381bcae92c/List/replicate sha256:b0e3ec1797b32c80c0bcb7e8254b08c7e9e35e75e6b410c7ac21477ab90167ad--- > 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:------ > { package = "dhall"--- > , author  = "Gabriel Gonzalez"--- > , license = ./LICENSE--- > }------ Normally if you wanted to import a text file you would need to wrap the--- contents of the file in double single-quotes, like this:------ > $ cat LICENSE--- > ''--- > Copyright (c) 2017 Gabriel Gonzalez--- > All rights reserved.--- > --- > ...--- > (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS--- > SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.--- > ''------ ... which does not work well if you need to reuse the same text file for--- other programs------ However, Dhall supports importing a raw text file by adding @as Text@ to the--- end of the import, like this:------ > { package = "dhall"--- > , author  = "Gabriel Gonzalez"--- > , license = ./LICENSE as Text--- > }------ ... and then you can use the original text file unmodified:------ > $ cat LICENSE--- > Copyright (c) 2017 Gabriel Gonzalez--- > All rights reserved.--- > --- > ...--- > (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS--- > SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.---- $format------ A format subcommand is also available that you can use to --- automatically format Dhall expressions.  For example, we can take the--- following unformatted Dhall expression:------ > $ cat ./unformatted--- > λ(a : Type) → λ(kvss : List (List { index : Natural, value : a })) → --- > List/build { index : Natural, value : a } (λ(list : Type) → λ(cons : { --- > index : Natural, value : a } → list → list) → λ(nil : list) → --- > (List/fold (List { index : Natural, value : a }) kvss { count : Natural, diff : --- > Natural → list } (λ(kvs : List { index : Natural, value : a }) → λ(y : { --- > count : Natural, diff : Natural → list }) → { count = y.count + List/length --- > { index : Natural, value : a } kvs, diff = λ(n : Natural) → List/fold { --- > index : Natural, value : a } kvs list (λ(kvOld : { index : Natural, value : a --- > }) → λ(z : list) → cons { index = kvOld.index + n, value = kvOld.value } --- > z) (y.diff (n + List/length { index : Natural, value : a } kvs)) }) { count = --- > 0, diff = λ(_ : Natural) → nil }).diff 0)------ ... and run the expression through the formatter:------ > $ dhall format < ./unformatted--- >   λ(a : Type)--- > → λ(kvss : List (List { index : Natural, value : a }))--- > → List/build--- >   { index : Natural, value : a }--- >   (   λ(list : Type)--- >     → λ(cons : { index : Natural, value : a } → list → list)--- >     → λ(nil : list)--- >     → ( List/fold--- >         (List { index : Natural, value : a })--- >         kvss--- >         { count : Natural, diff : Natural → list }--- >         (   λ(kvs : List { index : Natural, value : a })--- >           → λ(y : { count : Natural, diff : Natural → list })--- >           → { count = y.count + List/length { index : Natural, value : a } kvs--- >             , diff  =--- >                   λ(n : Natural)--- >                 → List/fold--- >                   { index : Natural, value : a }--- >                   kvs--- >                   list--- >                   (   λ(kvOld : { index : Natural, value : a })--- >                     → λ(z : list)--- >                     → cons { index = kvOld.index + n, value = kvOld.value } z--- >                   )--- >                   (y.diff (n + List/length { index : Natural, value : a } kvs))--- >             }--- >         )--- >         { count = 0, diff = λ(_ : Natural) → nil }--- >       ).diff--- >       0--- >   )------ The executable formats expressions without resolving, type-checking, or--- normalizing them:------ > $ dhall format--- > let replicate = https://raw.githubusercontent.com/dhall-lang/Prelude/35deff0d41f2bf86c42089c6ca16665537f54d75/List/replicate --- > in replicate 5 (List (List Natural)) (replicate 5 (List Natural) (replicate 5 Natural 1))--- > <Ctrl-D>--- >     let replicate =--- >           https://raw.githubusercontent.com/dhall-lang/Prelude/35deff0d41f2bf86c42089c6ca16665537f54d75/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):------ > $ dhall format --inplace ./unformatted--- > $ cat ./unformatted--- >   λ(a : Type)--- > → λ(kvss : List (List { index : Natural, value : a }))--- > → List/build--- >   { index : Natural, value : a }--- >   (   λ(list : Type)--- >     → λ(cons : { index : Natural, value : a } → list → list)--- >     → λ(nil : list)--- >     → ( List/fold--- >         (List { index : Natural, value : a })--- >         kvss--- >         { count : Natural, diff : Natural → list }--- >         (   λ(kvs : List { index : Natural, value : a })--- >           → λ(y : { count : Natural, diff : Natural → list })--- >           → { count = y.count + List/length { index : Natural, value : a } kvs--- >             , diff  =--- >                   λ(n : Natural)--- >                 → List/fold--- >                   { index : Natural, value : a }--- >                   kvs--- >                   list--- >                   (   λ(kvOld : { index : Natural, value : a })--- >                     → λ(z : list)--- >                     → cons { index = kvOld.index + n, value = kvOld.value } z--- >                   )--- >                   (y.diff (n + List/length { index : Natural, value : a } kvs))--- >             }--- >         )--- >         { count = 0, diff = λ(_ : Natural) → nil }--- >       ).diff--- >       0--- >   )------ Carefully note that the code formatter does not preserve all comments.--- Currently, the formatter only preserves leading comments and whitespace--- up until the last newline preceding the code.  In other words:------ > $ dhall format--- > {- This comment will be preserved by the formatter -}--- > -- ... and this comment will be preserved, too--- > {- This comment will *NOT* be preserved -} 1--- > -- ... and this comment will also *NOT* be preserved--- > <Ctrl-D>--- > {- This comment will be preserved by the formatter -}--- > -- ... and this comment will be preserved, too--- > 1------ Note that you do not need to format the output of the--- @dhall@ interpreter.  The interpreter already automatically formats--- multi-line expressions, too:------ > $ dhall--- > let replicate = https://raw.githubusercontent.com/dhall-lang/Prelude/35deff0d41f2bf86c42089c6ca16665537f54d75/List/replicate --- > in replicate 5 (List (List Natural)) (replicate 5 (List Natural) (replicate 5 Natural 1))--- > <Ctrl-D>--- > List (List (List Natural))--- > --- >   [   [ [ 1, 1, 1, 1, 1 ] : List Natural--- >       , [ 1, 1, 1, 1, 1 ] : List Natural--- >       , [ 1, 1, 1, 1, 1 ] : List Natural--- >       , [ 1, 1, 1, 1, 1 ] : List Natural--- >       , [ 1, 1, 1, 1, 1 ] : List Natural--- >       ]--- >     : List (List Natural)--- >   ,   [ [ 1, 1, 1, 1, 1 ] : List Natural--- >       , [ 1, 1, 1, 1, 1 ] : List Natural--- >       , [ 1, 1, 1, 1, 1 ] : List Natural--- >       , [ 1, 1, 1, 1, 1 ] : List Natural--- >       , [ 1, 1, 1, 1, 1 ] : List Natural--- >       ]--- >     : List (List Natural)--- >   ,   [ [ 1, 1, 1, 1, 1 ] : List Natural--- >       , [ 1, 1, 1, 1, 1 ] : List Natural--- >       , [ 1, 1, 1, 1, 1 ] : List Natural--- >       , [ 1, 1, 1, 1, 1 ] : List Natural--- >       , [ 1, 1, 1, 1, 1 ] : List Natural--- >       ]--- >     : List (List Natural)--- >   ,   [ [ 1, 1, 1, 1, 1 ] : List Natural--- >       , [ 1, 1, 1, 1, 1 ] : List Natural--- >       , [ 1, 1, 1, 1, 1 ] : List Natural--- >       , [ 1, 1, 1, 1, 1 ] : List Natural--- >       , [ 1, 1, 1, 1, 1 ] : List Natural--- >       ]--- >     : List (List Natural)--- >   ,   [ [ 1, 1, 1, 1, 1 ] : List Natural--- >       , [ 1, 1, 1, 1, 1 ] : List Natural--- >       , [ 1, 1, 1, 1, 1 ] : List Natural--- >       , [ 1, 1, 1, 1, 1 ] : List Natural--- >       , [ 1, 1, 1, 1, 1 ] : List Natural--- >       ]--- >     : List (List Natural)--- >   ]--- > : List (List (List Natural))---- $builtins------ Dhall is a restricted programming language that only supports simple built-in--- functions and operators.  If you want to do anything fancier you will need to--- load your data into Haskell for further processing------ This section covers types, functions, and operators that are built into the--- language, meaning that you do not need to import any code to use them.--- Additionally, Dhall also comes with a Prelude (covered in the next section)--- hosted online that contains functions derived from these base utilities.  The--- Prelude also re-exports all built-in functions for people who prefer--- consistency.------ The following documentation on built-ins is provided primarily as a reference.--- You don't need to read about every single built-in and you may want to skip to--- the following Prelude section.---- The language provides built-in support for the following primitive types:------ * @Bool@ values--- * @Natural@ values--- * @Integer@ values--- * @Double@ values--- * @Text@ values------ ... as well as support for the following derived types:------ * @List@s of values--- * @Optional@ values--- * Anonymous records--- * Anonymous unions---- $caveats------ Dhall differs in a few important ways from other programming languages, so--- you should keep the following caveats in mind:------ First, Dhall only supports addition and multiplication on @Natural@ numbers--- (i.e. non-negative integers), which are not the same type of number as--- @Integer@s (which can be negative).  An @Integer@ number is a number prefixed--- with either a @+@ or @-@ symbol whereas a @Natural@ number has no leading--- sign.  If you try to add or multiply two @Integer@s you will get a type--- error:------ > $ dhall--- > +2 + +2--- > <Ctrl-D>--- > Use "dhall --explain" for detailed errors--- > --- > Error: ❰+❱ only works on ❰Natural❱s--- > --- > +2 + +2--- > --- > (stdin):1:1------ In fact, there are no built-in functions for @Integer@s (or @Double@s).  As--- far as the language is concerned they are opaque values that can only be--- shuffled around but not used in any meaningful way until they have been--- loaded into Haskell.------ Second, the equality @(==)@ and inequality @(!=)@ operators only work on--- @Bool@s.  You cannot test any other types of values for equality.------ However, you can extend the language with your own built-ins using the--- Haskell API, as described in the next section.---- $extending------ You can use the Haskell API to extend the Dhall configuration language with--- new built-in functions.  This section contains a simple Haskell recipe to add--- a new @Natural/equal@ built-in function of type:------ > Natural/equal : Natural → Natural → Bool------ To do so, we:--- --- * extend the type-checking context to include the type of @Natural/equal@--- * extend the normalizer to evaluate all occurrences of @Natural/equal@------ ... like this:------ > -- example.hs--- > --- > {-# LANGUAGE OverloadedStrings #-}--- > --- > module Main where--- > --- > import Dhall.Core (Expr(..), ReifiedNormalizer(..))--- > --- > import qualified Data.Text.IO--- > import qualified Dhall--- > import qualified Dhall.Context--- > import qualified Lens.Family   as Lens--- > --- > main :: IO ()--- > main = do--- >     text <- Data.Text.IO.getContents--- > --- >     let startingContext = transform Dhall.Context.empty--- >           where--- >             transform = Dhall.Context.insert "Natural/equal" naturalEqualType--- > --- >             naturalEqualType =--- >                 Pi "_" Natural (Pi "_" Natural Bool)--- > --- >     let normalizer (App (App (Var "Natural/equal") (NaturalLit x)) (NaturalLit y)) =--- >             Just (BoolLit (x == y))--- >         normalizer _ =--- >             Nothing--- > --- >     let inputSettings = transform Dhall.defaultInputSettings--- >           where--- >             transform =--- >                   Lens.set Dhall.normalizer      (ReifiedNormalizer (pure . normalizer))--- >                 . Lens.set Dhall.startingContext startingContext--- > --- >     x <- Dhall.inputWithSettings inputSettings Dhall.auto text--- > --- >     Data.Text.IO.putStrLn x------ Here is an example use of the above program:------ > $ ./example <<< 'if Natural/equal 2 (1 + 1) then "Equal" else "Not equal"'--- > Equal------ Note that existing Dhall tools that type-check expressions will reject--- expressions containing unexpected free variable such as @Natural/equal@:------ > $ dhall <<< 'Natural/equal 2 (1 + 1)'--- > --- > Use "dhall --explain" for detailed errors--- > --- > Error: Unbound variable--- > --- > Natural/equal --- > --- > (stdin):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)---- $builtinOverview------ Each of the following sections provides an overview of builtin functions and--- operators for each type.  For each function you get:------ * An example use of that function------ * A \"type judgement\" explaining when that function or operator is well---   typed------ For example, for the following judgement:------ > Γ ⊢ x : Bool   Γ ⊢ y : Bool--- > ───────────────────────────--- > Γ ⊢ x && y : Bool------ ... you can read that as saying: "if @x@ has type @Bool@ and @y@ has type--- @Bool@, then @x && y@ has type @Bool@"------ Similarly, for the following judgement:------ > ─────────────────────────────────--- > Γ ⊢ Natural/even : Natural → Bool------ ... you can read that as saying: "@Natural/even@ always has type--- @Natural → Bool@"------ * Rules for how that function or operator behaves------ These rules are just equalities that come in handy when reasoning about code.--- For example, the section on @(&&)@ has the following rules:------ > (x && y) && z = x && (y && z)--- >--- > x && True = x--- >--- > True && x = x------ These rules are also a contract for how the compiler should behave.  If you--- ever observe code that does not obey these rules you should file a bug--- report.---- $bool------ There are two values that have type @Bool@ named @True@ and @False@:------ > ───────────────--- > Γ ⊢ True : Bool------ > ────────────────--- > Γ ⊢ False : Bool------ The built-in operations for values of type @Bool@ are:------- $or------ Example:------ > $ dhall--- > True || False--- > <Ctrl-D>--- > Bool--- > --- > True------ Type:------ > Γ ⊢ x : Bool   Γ ⊢ y : Bool--- > ───────────────────────────--- > Γ ⊢ x || y : Bool------ Rules:------ > (x || y) || z = x || (y || z)--- > --- > x || False = x--- > --- > False || x = x--- >--- > x || (y && z) = (x || y) && (x || z)--- > --- > x || True = True--- > --- > True || x = True---- $and------ Example:------ > $ dhall--- > True && False--- > <Ctrl-D>--- > Bool--- > --- > False------ Type:------ > Γ ⊢ x : Bool   Γ ⊢ y : Bool--- > ───────────────────────────--- > Γ ⊢ x && y : Bool------ Rules:------ > (x && y) && z = x && (y && z)--- > --- > x && True = x--- > --- > True && x = x--- >--- > x && (y || z) = (x && y) || (x && z)--- > --- > x && False = False--- > --- > False && x = False---- $equal------ Example:------ > $ dhall--- > True == False--- > <Ctrl-D>--- > Bool--- > --- > False------ Type:------ > Γ ⊢ x : Bool   Γ ⊢ y : Bool--- > ───────────────────────────--- > Γ ⊢ x == y : Bool------ Rules:------ > (x == y) == z = x == (y == z)--- > --- > x == True = x--- > --- > True == x = x--- >--- > x == x = True---- $unequal------ Example:------ > $ dhall--- > True != False--- > <Ctrl-D>--- > Bool--- > --- > True------ Type:------ > Γ ⊢ x : Bool   Γ ⊢ y : Bool--- > ───────────────────────────--- > Γ ⊢ x != y : Bool------ Rules:------ > (x != y) != z = x != (y != z)--- > --- > x != False = x--- > --- > False != x = x--- >--- > x != x = False---- $ifthenelse------ Example:------ > $ dhall--- > if True then 3 else 5--- > <Ctrl-D>--- > Natural--- > --- > 3------ Type:------ >                Γ ⊢ t : Type--- >                ─────────────────────--- > Γ ⊢ b : Bool   Γ ⊢ l : t   Γ ⊢ r : t--- > ────────────────────────────────────--- > Γ ⊢ if b then l else r : t------ Rules:------ > if b then True else False = b--- > --- > if True  then l else r = l--- > --- > if False then l else r = r---- $natural------ @Natural@ literals are non-negative numbers without any leading sign, like--- this:------ > 4 : Natural------ If you add a @+@ or @-@ sign then you get an @Integer@ literal, which is a--- different type of value---- $plus------ Example:------ > $ dhall--- > 2 + 3--- > <Ctrl-D>--- > Natural--- > --- > 5------ Type:------ > Γ ⊢ x : Natural   Γ ⊢ y : Natural--- > ─────────────────────────────────--- > Γ ⊢ x + y : Natural------ Rules:------ > (x + y) + z = x + (y + z)--- >--- > x + 0 = x--- >--- > 0 + x = x---- $times------ Example:------ > $ dhall--- > 2 * 3--- > <Ctrl-D>--- > Natural--- > --- > 6------ Type:------ > Γ ⊢ x : Natural   Γ ⊢ y : Natural--- > ─────────────────────────────────--- > Γ ⊢ x * y : Natural------ Rules:------ > (x * y) * z = x * (y * z)--- >--- > x * 1 = x--- >--- > 1 * x = x--- >--- > (x + y) * z = (x * z) + (y * z)--- >--- > x * (y + z) = (x * y) + (x * z)--- >--- > x * 0 = 0--- >--- > 0 * x = 0---- $even------ Example:------ > $ dhall--- > Natural/even 6--- > <Ctrl-D>--- > Bool--- > --- > True------ Type:------ > ─────────────────────────────────--- > Γ ⊢ Natural/even : Natural → Bool------ Rules:------ > Natural/even (x + y) = Natural/even x == Natural/even y--- >--- > Natural/even 0 = True--- >--- > Natural/even (x * y) = Natural/even x || Natural/even y--- >--- > Natural/even 1 = False---- $odd------ Example:------ > $ dhall--- > Natural/odd 6--- > <Ctrl-D>--- > Bool--- > --- > False------ Type:------ > ────────────────────────────────--- > Γ ⊢ Natural/odd : Natural → Bool------ Rules:------ > Natural/odd (x + y) = Natural/odd x != Natural/odd y--- >--- > Natural/odd 0 = False--- >--- > Natural/odd (x * y) = Natural/odd x && Natural/odd y--- >--- > Natural/odd 1 = True---- $isZero------ Example:------ > $ dhall--- > Natural/isZero 6--- > <Ctrl-D>--- > Bool--- > --- > False------ Type:------ > ───────────────────────────────────--- > Γ ⊢ Natural/isZero : Natural → Bool------ Rules:------ > Natural/isZero (x + y) = Natural/isZero x && Natural/isZero y--- >--- > Natural/isZero 0 = True--- >--- > Natural/isZero (x * y) = Natural/isZero x || Natural/isZero y--- >--- > Natural/isZero 1 = False---- $naturalFold------ Example:------ > $ dhall--- > Natural/fold 40 Text (λ(t : Text) → t ++ "!") "You're welcome"--- > <Ctrl-D>--- > Text--- > --- > "You're welcome!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"------ Type:------ > ──────────────────────────────────────────────────────────────────────────────────────────────────────────--- > Γ ⊢ Natural/fold : Natural → ∀(natural : Type) → ∀(succ : natural → natural) → ∀(zero : natural) → natural------ Rules:--- --- > Natural/fold (x + y) n s z = Natural/fold x n s (Natural/fold y n s z)--- > --- > Natural/fold 0 n s z = z--- > --- > Natural/fold (x * y) n s = Natural/fold x n (Natural/fold y n s)--- > --- > Natural/fold 1 n s = s---- $naturalBuild------ Example:------ > $ dhall--- > Natural/build (λ(natural : Type) → λ(succ : natural → natural) → λ(zero : natural) → succ (succ zero))--- > <Ctrl-D>--- > Natural--- > --- > 2------ Type:------ > ─────────────────────────────────────────────────────────────────────────────────────────────────────────────--- > Γ ⊢ Natural/build : (∀(natural : Type) → ∀(succ : natural → natural) → ∀(zero : natural) → natural) → Natural------ Rules:------ > Natural/fold (Natural/build x) = x--- >--- > Natural/build (Natural/fold x) = x---- $integer------ @Integer@ literals are prefixed with a @+@ (if they are non-negative) or a--- @-@ sign (if they are negative), like this:------ > +3 : Integer--- > -2 : Integer------ If you omit the sign then they are @Natural@ literals and not @Integer@s------ There are no built-in operations on @Integer@s.  For all practical purposes--- they are opaque values within the Dhall language---- $double------ A @Double@ literal is a floating point value with at least one decimal--- place, such as:------ > -2.0     : Double--- >  3.14159 : Double------ There are no built-in operations on @Double@s.  For all practical purposes--- they are opaque values within the Dhall language---- $text------ A @Text@ literal is just a sequence of characters enclosed in double quotes,--- like:------ > "ABC" : Text------ The only thing you can do with @Text@ values is concatenate them---- $textAppend------ Example:------ > $ dhall--- > "Hello, " ++ "world!"--- > <Ctrl-D>--- > Text--- > --- > "Hello, world!"------ Type:------ > Γ ⊢ x : Text   Γ ⊢ y : Text--- > ───────────────────────────--- > Γ ⊢ x && y : Text------ Rules:------ > (x ++ y) ++ z = x ++ (y ++ z)--- > --- > x ++ "" = x--- > --- > "" ++ x = x---- $list------ Dhall @List@ literals are a sequence of values inside of brackets separated by--- commas:------ > Γ ⊢ t : Type   Γ ⊢ x : t   Γ ⊢ y : t   ...--- > ──────────────────────────────────────────--- > Γ ⊢ [x, y, ... ] : List t------ Also, every empty @List@ must end with a mandatory type annotation, for example:------ > [] : List Natural------ The built-in operations on @List@s are:---- $listAppend------ Example:------ > $ dhall--- > [1, 2, 3] # [4, 5, 6]--- > <Ctrl-D>--- > List Natural--- >--- > [1, 2, 3, 4, 5, 6]------ Type:------ > Γ ⊢ x : List a    Γ ⊢ y : List a--- > ─────────────────────────────────--- > Γ ⊢ x # y : List a------ Rules:------ > ([] : List a) # xs = xs--- >--- > xs # ([] : List a) = xs--- >--- > (xs # ys) # zs = xs # (ys # zs)---- $listFold------ Example:------ > $ dhall--- > List/fold Bool [True, False, True] Bool (λ(x : Bool) → λ(y : Bool) → x && y) True--- > <Ctrl-D>--- > Bool--- > --- > False------ Type:------ > ────────────────────────────────────────────────────────────────────────────────────────────────────────--- > Γ ⊢ List/fold : ∀(a : Type) → List a → ∀(list : Type) → ∀(cons : a → list → list) → ∀(nil : list) → list------ Rules:------ > let Prelude/List/concat = https://raw.githubusercontent.com/dhall-lang/Prelude/35deff0d41f2bf86c42089c6ca16665537f54d75/List/concat--- >--- > List/fold a (Prelude/List/concat a xss) b c--- >     = List/fold (List a) xss b (λ(x : List a) → List/fold a x b c)--- >--- > List/fold a ([] : List a) b c n = n--- >--- > List/fold a ([x] : List a) b c = c x---- $listBuild------ Example:------ > $ dhall--- > List/build Natural (λ(list : Type) → λ(cons : Natural → list → list) → λ(nil : list) → cons 1 (cons 2 (cons 3 nil)))--- > <Ctrl-D>--- > List Natural--- > --- > [1, 2, 3] : List Natural------ Type:------ > ───────────────────────────────────────────────────────────────────────────────────────────────────────────--- > Γ ⊢ List/build : ∀(a : Type) → (∀(list : Type) → ∀(cons : a → list → list) → ∀(nil : list) → list) → List a------ Rules:------ > List/build t (List/fold t x) = x--- >--- > List/fold t (List/build t x) = x---- $listLength------ Example:------ > $ dhall--- > List/length Natural [1, 2, 3]--- > <Ctrl-D>--- > Natural--- > --- > 3------ Type:------ > ────────────────────────────────────────────────--- > Γ ⊢ List/length : ∀(a : Type) → List a → Natural------ Rules:------ > List/length t xs = List/fold t xs Natural (λ(_ : t) → λ(n : Natural) → n + 1) 0---- $listHead------ Example:------ > $ dhall--- > List/head Natural [1, 2, 3]--- > <Ctrl-D>--- > Optional Natural--- > --- > Some 1------ Type:------ > ───────────────────────────────────────────────--- > Γ ⊢ List/head ∀(a : Type) → List a → Optional a------ Rules:------ > let Prelude/Optional/head  = https://raw.githubusercontent.com/dhall-lang/Prelude/35deff0d41f2bf86c42089c6ca16665537f54d75/Optional/head--- > let Prelude/List/concat    = https://raw.githubusercontent.com/dhall-lang/Prelude/35deff0d41f2bf86c42089c6ca16665537f54d75/List/concat--- > let Prelude/List/concatMap = https://raw.githubusercontent.com/dhall-lang/Prelude/35deff0d41f2bf86c42089c6ca16665537f54d75/List/concatMap--- > let Prelude/List/map       = https://raw.githubusercontent.com/dhall-lang/Prelude/35deff0d41f2bf86c42089c6ca16665537f54d75/List/map--- > --- > List/head a (Prelude/List/concat a xss) =--- >     Prelude/Optional/head a (Prelude/List/map (List a) (Optional a) (List/head a) xss)--- > --- > List/head a ([x] : List a) = Some x--- > --- > List/head b (Prelude/List/concatMap a b f m)--- >     = Prelude/Optional/concatMap a b (λ(x : a) → List/head b (f x)) (List/head a m)---- $listLast------ Example:------ > $ dhall--- > List/last Natural [1, 2, 3]--- > <Ctrl-D>--- > Optional Natural--- > --- > Some 1------ Type:------ > ─────────────────────────────────────────────────--- > Γ ⊢ List/last : ∀(a : Type) → List a → Optional a------ Rules:------ > let Prelude/Optional/last  = https://raw.githubusercontent.com/dhall-lang/Prelude/35deff0d41f2bf86c42089c6ca16665537f54d75/Optional/last--- > let Prelude/List/concat    = https://raw.githubusercontent.com/dhall-lang/Prelude/35deff0d41f2bf86c42089c6ca16665537f54d75/List/concat--- > let Prelude/List/concatMap = https://raw.githubusercontent.com/dhall-lang/Prelude/35deff0d41f2bf86c42089c6ca16665537f54d75/List/concatMap--- > let Prelude/List/map       = https://raw.githubusercontent.com/dhall-lang/Prelude/35deff0d41f2bf86c42089c6ca16665537f54d75/List/map--- > --- > List/last a (Prelude/List/concat a xss) =--- >     Prelude/Optional/last a (Prelude/List/map (List a) (Optional a) (List/last a) xss)--- > --- > List/last a ([x] : List a) = Some x--- > --- > List/last b (Prelude/List/concatMap a b f m)--- >     = Prelude/Optional/concatMap a b (λ(x : a) → List/last b (f x)) (List/last a m)---- $listIndexed------ Example------ > $ dhall--- > List/indexed Text ["ABC", "DEF", "GHI"]--- > <Ctrl-D>--- > List { index : Natural, value : Text }--- > --- > [{ index = 0, value = "ABC" }, { index = 1, value = "DEF" }, { index = 2, value = "GHI" }] : List { index : Natural, value : Text }------ Type:------ > ─────────────────────────────────────────────────────────────────────────────--- > Γ ⊢ List/indexed : ∀(a : Type) → List a → List { index : Natural, value : a }------ Rules:------ > let Prelude/List/shifted = https://raw.githubusercontent.com/dhall-lang/Prelude/35deff0d41f2bf86c42089c6ca16665537f54d75/List/shifted--- > let Prelude/List/concat  = https://raw.githubusercontent.com/dhall-lang/Prelude/35deff0d41f2bf86c42089c6ca16665537f54d75/List/concat--- > let Prelude/List/map     = https://raw.githubusercontent.com/dhall-lang/Prelude/35deff0d41f2bf86c42089c6ca16665537f54d75/List/map--- > --- > List/indexed a (Prelude/List/concat a xss) =--- >     Prelude/List/shifted a (Prelude/List/map (List a) (List { index : Natural, value : a }) (List/indexed a) xss)---- $listReverse------ Example:------ > $ dhall--- > List/reverse Natural [1, 2, 3]--- > <Ctrl-D>--- > List Natural--- > --- > [3, 2, 1] : List Natural------ Type:------ > ─────────────────────────────────────────────────--- > Γ ⊢ List/reverse : ∀(a : Type) → List a → List a------ Rules:------ > let Prelude/List/map       = https://raw.githubusercontent.com/dhall-lang/Prelude/35deff0d41f2bf86c42089c6ca16665537f54d75/List/map--- > let Prelude/List/concat    = https://raw.githubusercontent.com/dhall-lang/Prelude/35deff0d41f2bf86c42089c6ca16665537f54d75/List/concat--- > let Prelude/List/concatMap = https://raw.githubusercontent.com/dhall-lang/Prelude/35deff0d41f2bf86c42089c6ca16665537f54d75/List/concatMap--- > --- > List/reverse a (Prelude/List/concat a xss)--- >     = Prelude/List/concat a (List/reverse (List a) (Prelude/List/map (List a) (List a) (List/reverse a) xss))--- >--- > List/reverse a ([x] : List a) = [x] : List a--- >--- > List/reverse b (Prelude/List/concatMap a b f xs)--- >     = Prelude/List/concatMap a b (λ(x : a) → List/reverse b (f x)) (List/reverse a xs)--- >--- > List/reverse a ([x, y] : List a) = [y, x] : List a---- $optional1------ Dhall @Optional@ literals are either @Some@ followed by a value:------ > Γ ⊢ x : t   Γ ⊢ t : Type--- > ────────────────────────--- > Γ ⊢ Some x : Optional t------ ... or @None@ followed by a type:------ > ───────────────────────────────────--- > Γ ⊢ None : ∀(t : Type) → Optional t------ Note that `None` is a valid standalone function------ The built-in operations on @Optional@ values are:---- $optionalFold------ Example:------ > $ dhall--- > Optional/fold Text (Some "ABC") Text (λ(t : Text) → t) ""--- > <Ctrl-D>--- > Text--- > --- > "ABC"------ Type:------ > ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────--- > Γ ⊢ Optional/fold : ∀(a : Type) → Optional a → ∀(optional : Type) → ∀(some : a → optional) → ∀(none : optional) → optional------ Rules:------ > Optional/fold a (None a) o j n = n--- >--- > Optional/fold a (Some x) o j n = j x---- $prelude------ There is also a Prelude available at:------ <http://prelude.dhall-lang.org>------ ... which currenty redirects to:------ <https://raw.githubusercontent.com/dhall-lang/Prelude/35deff0d41f2bf86c42089c6ca16665537f54d75>------ There is nothing \"official\" or \"standard\" about this Prelude other than--- the fact that it is mentioned in this tutorial.  The \"Prelude\" is just a--- set of convenient utilities which didn't quite make the cut to be built into--- the language.  Feel free to host your own custom Prelude if you want!------ If you visit the above link you can browse the Prelude, which has a few--- subdirectories.  For example, the @Bool@ subdirectory has a @not@ file--- located here:------ <https://raw.githubusercontent.com/dhall-lang/Prelude/35deff0d41f2bf86c42089c6ca16665537f54d75/Bool/not>------ The @not@ function is just a UTF8-encoded text file hosted online with the--- following contents------ > $ curl https://raw.githubusercontent.com/dhall-lang/Prelude/35deff0d41f2bf86c42089c6ca16665537f54d75/Bool/not--- > {---- > Flip the value of a `Bool`--- > --- > Examples:--- > --- > ```--- > ./not True = False--- > --- > ./not False = True--- > ```--- > -}--- > let not : Bool → Bool--- >     =   λ(b : Bool) → b == False--- > --- > in  not------ The file could have been much shorter, like this:------ > λ(b : Bool) → b == False------ ... but all the functions exported from the Prelude try to be as--- self-documenting as possible by including:------ * the name of the function--- * the type of the function--- * documentation (including a few examples)------ The performance penalty for adding these helpful features is negligible.------ You can use this @not@ function either directly:------ > $ dhall--- > https://raw.githubusercontent.com/dhall-lang/Prelude/35deff0d41f2bf86c42089c6ca16665537f54d75/Bool/not True--- > <Ctrl-D>--- > Bool--- > --- > False------ ... or assign the URL to a shorter name:------ > $ dhall--- > let Bool/not = https://raw.githubusercontent.com/dhall-lang/Prelude/35deff0d41f2bf86c42089c6ca16665537f54d75/Bool/not--- > in  Bool/not True--- > <Ctrl-D>--- > Bool--- > --- > False------ Some functions in the Prelude just re-export built-in functions for--- consistency and documentation, such as @Prelude\/Natural\/even@, which--- re-exports the built-in @Natural/even@ function:------ > $ curl https://raw.githubusercontent.com/dhall-lang/Prelude/35deff0d41f2bf86c42089c6ca16665537f54d75/Natural/even--- > {---- > Returns `True` if a number if even and returns `False` otherwise--- > --- > Examples:--- > --- > ```--- > ./even 3 = False--- > --- > ./even 0 = True--- > ```--- > -}--- > let even : Natural → Bool--- >     =   Natural/even--- > --- > in  even------ You can also clone the Prelude locally to your filesystem if you prefer--- using `git clone`, like this:------ > $ git clone https://github.com/dhall-lang/Prelude.git--- > $ tree Prelude--- > Prelude--- > ├── Bool--- > │   ├── and--- > │   ├── build--- > │   ├── even--- > │   ├── fold--- > │   ├── not--- > │   ├── odd--- > │   ├── or--- > │   ├── package.dhall--- > │   └── show--- > ├── Double--- > │   ├── package.dhall--- > │   └── show--- > ├── Integer--- > │   ├── package.dhall--- > │   └── show--- > ├── List--- > │   ├── all--- > │   ├── any--- > │   ├── build--- > │   ├── concat--- > │   ├── concatMap--- > │   ├── filter--- > │   ├── fold--- > │   ├── generate--- > │   ├── head--- > │   ├── indexed--- > │   ├── iterate--- > │   ├── last--- > │   ├── length--- > │   ├── map--- > │   ├── null--- > │   ├── package.dhall--- > │   ├── replicate--- > │   ├── reverse--- > │   ├── shifted--- > │   └── unzip--- > ├── Monoid--- > ├── Natural--- > │   ├── build--- > │   ├── enumerate--- > │   ├── even--- > │   ├── fold--- > │   ├── isZero--- > │   ├── odd--- > │   ├── package.dhall--- > │   ├── product--- > │   ├── show--- > │   ├── sum--- > │   └── toInteger--- > ├── Optional--- > │   ├── None--- > │   ├── Some--- > │   ├── all--- > │   ├── any--- > │   ├── build--- > │   ├── concat--- > │   ├── filter--- > │   ├── fold--- > │   ├── head--- > │   ├── last--- > │   ├── length--- > │   ├── map--- > │   ├── null--- > │   ├── package.dhall--- > │   ├── toList--- > │   └── unzip--- > ├── Record--- > │   ├── keyText--- > │   ├── keyValue--- > │   └── package.dhall--- > ├── Text--- > │   ├── concat--- > │   ├── concatMap--- > │   ├── concatMapSep--- > │   ├── concatSep--- > │   └── package.dhall--- > └── package.dhall--- > --- > 8 directories, 70 files------ Browse the Prelude online to learn more by seeing what functions are--- available and reading their inline documentation:------ <https://github.com/dhall-lang/Prelude>------ __Exercise__: Try to use a new Prelude function that has not been covered--- previously in this tutorial------ You can also import the entire Prelude as a single large record for--- convenience:------ > $ dhall--- >     let Prelude = https://raw.githubusercontent.com/dhall-lang/Prelude/35deff0d41f2bf86c42089c6ca16665537f54d75/package.dhall--- >--- > in    λ(x : Text)--- >     → Prelude.`List`.length Text (Prelude.`List`.replicate 10 Text x)--- > <Ctrl-D>--- > ∀(x : Text) → Natural--- >--- > λ(x : Text) → 10------ The organization of the package mirrors the layout of the Prelude, meaning--- that every directory is stored as a record whose children are the fields of--- that record.------ __Exercise__: Browse the Prelude by running:------ > $ dhall <<< 'https://raw.githubusercontent.com/dhall-lang/Prelude/35deff0d41f2bf86c42089c6ca16665537f54d75/package.dhall'---- $conclusion------ By this point you should be able to use the Dhall configuration language to--- author, import, and program configuration files.  If you run into any issues--- you can report them at:------ <https://github.com/dhall-lang/dhall-haskell/issues>------ You can also request features, support, or documentation improvements on the--- above issue tracker.------ If you would like to contribute to the Dhall project you can try to port Dhall--- to other languages besides Haskell so that Dhall configuration files can be--- read into those languages, too.---- $faq------ * Why do empty lists require a type annotation?------ Unlike Haskell, Dhall cannot infer a polymorphic type for the empty list--- because Dhall represents polymorphic values as functions of types, like this:------ > λ(a : Type) → [] : List a------ If the compiler treated an empty list literal as syntactic short-hand for--- the above polymorphic function then you'd get the unexpected behavior where--- a list literal is a function if the list has 0 elements but not a function--- otherwise.--- --- * Does Dhall support user-defined recursive types?------ No, but you can translate recursive code to non-recursive code by following--- this guide:------ <https://github.com/dhall-lang/dhall-lang/wiki/How-to-translate-recursive-code-to-Dhall How to translate recursive code to Dhall>+{-# LANGUAGE CPP #-}++{-| Dhall is a programming language specialized for configuration files.  This+    module contains a tutorial explaining how to author configuration files+    using this language++    You might also be interested in the+    <https://docs.dhall-lang.org/tutorials/Language-Tour.html Language Tour>, a+    Haskell-agnostic tour of Dhall's language features.+-}+module Dhall.Tutorial (+    -- * Introduction+    -- $introduction++    -- * Types+    -- $types++    -- * Imports+    -- $imports++    -- * Lists+    -- $lists++    -- * Optional values+    -- $optional0++    -- * Records+    -- $records++    -- * Functions+    -- $functions++    -- * Compiler+    -- $compiler++    -- * Strings+    -- $strings++    -- * Combine+    -- $combine++    -- * Let expressions+    -- $let++    -- * Defaults+    -- $defaults++    -- * Unions+    -- $unions++    -- * Polymorphic functions+    -- $polymorphic++    -- * Total+    -- $total++    -- * Assertions+    -- $assertions++    -- * Headers+    -- $headers++    -- * Import integrity+    -- $integrity++    -- * Raw text+    -- $rawText++    -- * Formatting code+    -- $format++    -- * Built-in functions+    -- $builtins++    -- ** Caveats+    -- $caveats++    -- ** Extending the language+    -- $extending++    -- ** Substitutions+    -- $substitutions++    -- * Prelude+    -- $prelude++    -- * Limitations+    -- $limitations++    -- * Conclusion+    -- $conclusion++    -- * Frequently Asked Questions (FAQ)+    -- $faq+    ) where++import Data.Vector (Vector)+import Dhall++-- $setup+--+-- >>> :set -XOverloadedStrings++-- $introduction+--+-- The simplest way to use Dhall is to ignore the programming language features+-- and use it as a strongly typed configuration format.  For example, suppose+-- that you create the following configuration file:+--+-- > -- ./config.dhall+-- > { foo = 1+-- > , bar = [3.0, 4.0, 5.0]+-- > }+--+-- You can read the above configuration file into Haskell using the following+-- code:+--+-- > -- example.hs+-- >+-- > {-# LANGUAGE DeriveGeneric     #-}+-- > {-# LANGUAGE OverloadedStrings #-}+-- >+-- > import Dhall+-- >+-- > data Example = Example { foo :: Natural, bar :: Vector Double }+-- >     deriving (Generic, Show)+-- >+-- > instance FromDhall Example+-- >+-- > main :: IO ()+-- > main = do+-- >     x <- input auto "./config.dhall"+-- >     print (x :: Example)+--+-- __WARNING__: You must not instantiate FromDhall with a recursive type. See [Limitations](#limitations).+--+-- If you compile and run the above example, the program prints the corresponding+-- Haskell record:+--+-- > $ ./example+-- > Example {foo = 1, bar = [3.0,4.0,5.0]}+--+-- You can also load some types directly into Haskell without having to define a+-- record, like this:+--+-- >>> import Dhall+-- >>> :set -XOverloadedStrings+-- >>> input auto "True" :: IO Bool+-- True+--+-- The `Dhall.input` function can decode any value if we specify the value's+-- expected `Dhall.Type`:+--+-- > input+-- >     :: Type a  -- Expected type+-- >     -> Text    -- Dhall program+-- >     -> IO a    -- Decoded expression+--+-- ... and we can either specify an explicit type like `bool`:+--+-- > bool :: Type Bool+-- >+-- > input bool :: Text -> IO Bool+-- >+-- > input bool "True" :: IO Bool+--+-- >>> input bool "True"+-- True+--+-- ... or we can use `auto` to let the compiler infer what type to decode from+-- the expected return type:+--+-- > auto :: FromDhall a => Type a+-- >+-- > input auto :: FromDhall a => Text -> IO a+--+-- >>> input auto "True" :: IO Bool+-- True+--+-- You can see what types `auto` supports \"out-of-the-box\" by browsing the+-- instances for the `FromDhall` class.  For example, the following instance+-- says that we can directly decode any Dhall expression that evaluates to a+-- @Bool@ into a Haskell `Prelude.Bool`:+--+-- > instance FromDhall Bool+--+-- ... which is why we could directly decode the string @\"True\"@ into the+-- value `True`.+--+-- There is also another instance that says that if we can decode a value of+-- type @a@, then we can also decode a @List@ of values as a `Vector` of @a@s:+--+-- > instance FromDhall a => FromDhall (Vector a)+--+-- Therefore, since we can decode a @Bool@, we must also be able to decode a+-- @List@ of @Bool@s, like this:+--+-- >>> input auto "[True, False]" :: IO (Vector Bool)+-- [True,False]+--+-- We could also specify what type to decode by providing an explicit+-- `Dhall.Type` instead of using `auto` with a type annotation:+--+-- >>> input (vector bool) "[True, False]"+-- [True,False]+--+-- __Exercise:__ Create a @./config.dhall@ file that the following program can+-- decode:+--+-- > {-# LANGUAGE DeriveAnyClass    #-}+-- > {-# LANGUAGE DeriveGeneric     #-}+-- > {-# LANGUAGE OverloadedStrings #-}+-- >+-- > import Dhall+-- >+-- > data Person = Person { age :: Natural, name :: Text }+-- >     deriving (Generic, FromDhall, Show)+-- >+-- > main :: IO ()+-- > main = do+-- >     x <- input auto "./config.dhall"+-- >     print (x :: Person)+--+-- __Exercise:__ Create a @./config.dhall@ file that the following program can+-- decode:+--+-- > {-# LANGUAGE OverloadedStrings #-}+-- >+-- > import Data.Functor.Identity+-- > import Dhall+-- >+-- > instance FromDhall a => FromDhall (Identity a)+-- >+-- > main :: IO ()+-- > main = do+-- >     x <- input auto "./config.dhall"+-- >     print (x :: Identity Double)++-- $types+--+-- Suppose that we try to decode a value of the wrong type, like this:+--+-- >>> input auto "1" :: IO Bool+-- *** Exception:+-- ...Error...: Expression doesn't match annotation+-- ...+-- - Bool+-- + Natural+-- ...+-- 1│ 1 : Bool+-- ...+-- (input):1:1+-- ...+--+-- The interpreter complains because the string @\"1\"@ cannot be decoded into a+-- Haskell value of type `Prelude.Bool`.  This part of the type error:+--+-- > - Bool+-- > + Natural+--+-- ... means that the expected type was @Bool@ but the inferred type of the+-- expression @1@ was @Natural@.+--+-- The code excerpt from the above error message has two components:+--+-- * the expression being type checked (i.e. @1@)+-- * the expression's expected type (i.e. @Bool@)+--+-- > Expression+-- > ⇩+-- > 1 : Bool+-- >     ⇧+-- >     Expected type+--+-- The @(:)@ symbol is how Dhall annotates values with their expected types.+-- This notation is equivalent to type annotations in Haskell using the @(::)@+-- symbol.  Whenever you see:+--+-- > x : t+--+-- ... you should read that as \"we expect the expression @x@ to have type+-- @t@\". However, we might be wrong and if our expected type does not match the+-- expression's actual type then the type checker will complain.+--+-- In this case, the expression @1@ does not have type @Bool@ so type checking+-- fails with an exception.+--+-- __Exercise:__ Load the Dhall library into @ghci@ and run these commands to get+-- get a more detailed error message:+--+-- > >>> import Dhall+-- > >>> :set -XOverloadedStrings+-- > >>> detailed (input auto "1") :: IO Bool+-- > ...+--+-- ... then read the entire error message+--+-- __Exercise:__ Fix the type error, either by changing the value to decode or+-- changing the expected type++-- $imports+--+-- You might wonder why in some cases we can decode a configuration file:+--+-- >>> writeFile "bool" "True"+-- >>> input auto "./bool" :: IO Bool+-- True+--+-- ... and in other cases we can decode a value directly:+--+-- >>> input auto "True" :: IO Bool+-- True+--+-- This is because importing a configuration from a file is a special case of a+-- more general language feature: Dhall expressions can reference other+-- expressions by their file path.+--+-- To illustrate this, let's create three files:+--+-- > $ echo "True"  > bool1+-- > $ echo "False" > bool2+-- > $ echo "./bool1 && ./bool2" > both+--+-- ... and read in all three files in a single expression:+--+-- >>> input auto "[ ./bool1 , ./bool2 , ./both ]" :: IO (Vector Bool)+-- [True,False,False]+--+-- Each file path is replaced with the Dhall expression contained within that+-- file.  If that file contains references to other files then those references+-- are transitively resolved.+--+-- In other words: configuration files can reference other configuration files,+-- either by their relative or absolute paths.  This means that we can split a+-- configuration file into multiple files, like this:+--+-- > -- ./config.dhall+-- > { foo = 1+-- > , bar = ./bar.dhall+-- > }+--+-- > -- ./bar.dhall+-- > [3.0, 4.0, 5.0]+--+-- ... which is equivalent to our original configuration:+--+-- > -- ./config.dhall+-- > { foo = 1+-- > , bar = [3.0, 4.0, 5.0]+-- > }+--+-- However, the Dhall language will forbid cycles in these file references.  For+-- example, if we create the following cycle:+--+-- > $ echo './file1' > file2+-- > $ echo './file2' > file1+--+-- ... then the interpreter will reject the import:+--+-- >>> input auto "./file1" :: IO Natural+-- *** Exception:+-- ↳ ./file1+--   ↳ ./file2+-- ...+-- Cyclic import: ./file1+-- ...+--+-- You can also import expressions by URL.  For example, you can find a Dhall+-- expression hosted at this GitHub URL:+--+-- <https://raw.githubusercontent.com/dhall-lang/dhall-haskell/18e4e9a18dc53271146df3ccf5b4177c3552236b/examples/True>+--+-- > $ curl https://raw.githubusercontent.com/dhall-lang/dhall-haskell/18e4e9a18dc53271146df3ccf5b4177c3552236b/examples/True+-- > True+--+-- ... and you can reference that expression either directly:+--+#if defined(WITH_HTTP) && defined(USE_HTTP_CLIENT_TLS) && defined(NETWORK_TESTS)+-- >>> input auto "https://raw.githubusercontent.com/dhall-lang/dhall-haskell/18e4e9a18dc53271146df3ccf5b4177c3552236b/examples/True" :: IO Bool+-- True+#else+-- > >>> input auto "https://raw.githubusercontent.com/dhall-lang/dhall-haskell/18e4e9a18dc53271146df3ccf5b4177c3552236b/examples/True" :: IO Bool+-- > True+#endif+--+-- ... or inside of a larger expression:+--+#if defined(WITH_HTTP) && defined(USE_HTTP_CLIENT_TLS) && defined(NETWORK_TESTS)+-- >>> input auto "False == https://raw.githubusercontent.com/dhall-lang/dhall-haskell/18e4e9a18dc53271146df3ccf5b4177c3552236b/examples/True" :: IO Bool+-- False+#else+-- > >>> input auto "False == https://raw.githubusercontent.com/dhall-lang/dhall-haskell/18e4e9a18dc53271146df3ccf5b4177c3552236b/examples/True" :: IO Bool+-- > False+#endif+--+-- You're not limited to hosting Dhall expressions on GitHub.  You can host a+-- Dhall expression anywhere that you can host UTF8-encoded text on the web,+-- such as a pastebin, or your own web server.+--+-- You can also import Dhall expressions from environment variables, too:+--+-- >>> System.Environment.setEnv "FOO" "1"+-- >>> input auto "env:FOO" :: IO Natural+-- 1+--+-- You can import types, too.  For example, we can change our @./bar@ file to:+--+-- > -- ./bar.dhall+-- > [3.0, 4.0, 5.0] : List ./type.dhall+--+-- ... then specify the type in a separate file:+--+-- > -- ./type.dhall+-- > Double+--+-- ... and everything still type checks:+--+-- > $ ./example+-- > Example {foo = 1, bar = [3.0,4.0,5.0]}+--+-- Note that imports should be terminated by whitespace or parentheses otherwise+-- you will get either an import error or a parse error, like this:+--+-- >>> writeFile "baz" "2.0"+-- >>> input auto "./baz: Double" :: IO Double+-- *** Exception:+-- ↳ ./baz:+-- ...+-- ...Error...: Missing file ...baz:+-- ...+--+-- This is because the parser thinks that @./baz:@ is a single token due to+-- the missing whitespace before the colon and tries to import a file named+-- @./baz:@, which does not exist.  To fix the problem we have to add a space+-- after @./baz@:+--+-- >>> input auto "./baz : Double" :: IO Double+-- 2.0+--+-- __Exercise:__ There is a @not@ function hosted online here:+--+-- <https://prelude.dhall-lang.org/Bool/not>+--+-- Visit that link and read the documentation.  Then try to guess what this+-- code returns:+--+-- > >>> input auto "https://prelude.dhall-lang.org/Bool/not https://raw.githubusercontent.com/dhall-lang/dhall-haskell/18e4e9a18dc53271146df3ccf5b4177c3552236b/examples/True" :: IO Bool+-- > ???+--+-- Run the code to test your guess++-- $lists+--+-- You can store 0 or more values of the same type in a list, like this:+--+-- > [1, 2, 3]+--+-- Every list can be followed by the type of the list.  The type annotation is+-- required for empty lists but optional for non-empty lists.  You will get a+-- parse error if you provide an empty list without a type annotation:+--+-- >>> input auto "[]" :: IO (Vector Natural)+-- *** Exception:+-- ...Error...: Invalid input+-- ...+-- (input):1:3:+--   |+-- 1 | []+--   |   ^+-- Empty list literal without annotation+-- ...+--+-- Also, list elements must all have the same type.  You will get an error if+-- you try to store elements of different types in a list:+--+-- >>> input auto "[1, True, 3]" :: IO (Vector Natural)+-- *** Exception:+-- ...Error...: List elements should all have the same type+-- ...+-- - Natural+-- + Bool+-- ...+-- 1│     True+-- ...+-- (input):1:5+-- ...+--+-- __Exercise:__ Replace the @\"???\"@ with an expression that successfully+-- decodes to the specified type:+--+-- > >>> input auto "???" :: IO (Vector (Vector Natural))++-- $optional0+--+-- @Optional@ values are either of the form @Some value@ or @None type@.+--+-- For example, these are valid @Optional@ values:+--+-- > Some 1+-- >+-- > None Natural+--+-- ... which both have type @Optional Natural@+--+-- An @Optional@ corresponds to Haskell's `Maybe` type for decoding purposes:+--+-- >>> input auto "Some 1" :: IO (Maybe Natural)+-- Just 1+-- >>> input auto "None Natural" :: IO (Maybe Natural)+-- Nothing+--+-- __Exercise:__ Replace the @\"???\"@ with an expression that successfully+-- decodes to the specified type:+--+-- > >>> input auto "???" :: IO (Maybe (Maybe (Maybe Natural)))++-- $records+--+-- Record literals are delimited by curly braces and their fields are separated+-- by commas.  For example, this is a valid record literal:+--+-- > { foo = True+-- > , bar = 2+-- > , baz = 4.2+-- > }+--+-- A record type is like a record literal except instead of specifying each+-- field's value we specify each field's type.  For example, the preceding+-- record literal has the following record type:+--+-- > { foo : Bool+-- > , bar : Natural+-- > , baz : Double+-- > }+--+-- If you want to specify an empty record literal, you must use @{=}@, which is+-- special syntax reserved for empty records.  If you want to specify the empty+-- record type, then you use @{}@.  If you forget which is which you can always+-- ask the @dhall@ compiler to remind you of the type for each one:+--+-- > $ dhall type <<< '{=}'+-- > {}+--+-- > $ dhall type <<< '{}'+-- > Type+--+-- This is our first use of the @dhall@ command-line tool (provided by this+-- package), which provides a @type@ subcommand for inferring an expression's+-- type.  By default the tool reads the expression on standard input and outputs+-- the type to standard output.+--+-- Note that @<<<@ is a feature specific to the Bash shell to feed a string to+-- a command's standard input.  If you are using another shell, then you can+-- instead do this:+--+-- > $ echo '{=}' | dhall type+-- > {}+--+-- __Exercise__: Use the @dhall type@ command to infer the type of this record:+--+-- > -- ./nested.dhall+-- > { foo = 1+-- > , bar =+-- >     { baz = 2.0+-- >     , qux = True+-- >     }+-- > }+--+-- You can specify nested fields using dot-separated keys, like this:+--+-- > { foo = 1, bar.baz = 2.0, bar.qux = True }+--+-- ... which is equivalent to:+--+-- > { foo = 1, bar = { baz = 2.0, qux = True } }+--+-- You can also access a field of a record using the following syntax:+--+-- > record.fieldName+--+-- ... which means to access the value of the field named @fieldName@ from the+-- @record@.  For example:+--+-- >>> input auto "{ foo = True, bar = 2, baz = 4.2 }.baz" :: IO Double+-- 4.2+--+-- ... and you can project out multiple fields into a new record using this+-- syntax:+--+-- > someRecord.{ field₀, field₁, … }+--+-- For example:+--+-- > $ dhall <<< '{ x = 1, y = True, z = "ABC" }.{ x, y }'+-- > { x = 1, y = True }+--+-- This is our first example of using the @dhall@ command-line tool with no+-- subcommand (like @type@), which evaluates the provided expression.  By+-- default, this reads the expression on standard input and outputs the+-- evaluated result on standard output.+--+-- __Exercise__: Save the above @./nested.dhall@ file and then try to access the+-- value of the @baz@ field.  Test that this works by interpreting your code+-- using the @dhall@ command.+--+-- You can convert a record to a list of key-value pairs (a.k.a. a \"Map\") by+-- using the @toMap@ keyword.  For example:+--+-- > $ dhall <<< 'toMap { foo = 1, bar = 2 }'+-- > [ { mapKey = "bar", mapValue = 2 }, { mapKey = "foo", mapValue = 1 } ]+--+-- This conversion only works if all field of the record have the same type.+-- This comes in handy when you need to convert a Dhall record to the Dhall+-- equivalent of a homogeneous map (i.e. Haskell's @"Data.Map"@).++-- $functions+--+-- The Dhall programming language also supports user-defined anonymous+-- functions.  For example, we can save the following anonymous function to a+-- file:+--+-- > -- ./makeBools.dhall+-- > \(n : Bool) ->+-- >     [ n && True, n && False, n || True, n || False ]+--+-- ... or we can use Dhall's support for Unicode characters to use @λ@ (U+03BB)+-- instead of @\\@ and @→@ (U+2192) instead of @->@ (for people who are into+-- that sort of thing):+--+-- > $ -- ./makeBools.dhall+-- > λ(n : Bool) →+-- >     [ n && True, n && False, n || True, n || False ]+-- > <Ctrl-D>+--+-- We'll be sticking to ASCII for the remainder of the tutorial, though, while+-- still pointing out Unicode equivalents as we go.+--+-- You can read this as a function of one argument named @n@ that has type+-- @Bool@.  This function returns a @List@ of @Bool@s.  Each element of the+-- @List@ depends on the input argument named @n@.+--+-- The (ASCII) syntax for anonymous functions resembles the syntax for anonymous+-- functions in Haskell.  The only difference is that Dhall requires you to+-- annotate the type of the function's input.+--+-- You can import this function into Haskell, too:+--+-- >>> makeBools <- input auto "./makeBools.dhall" :: IO (Bool -> Vector Bool)+-- >>> makeBools True+-- [True,False,True,True]+--+-- The reason this works is that there is an `FromDhall` instance for simple+-- functions:+--+-- > instance (ToDhall a, FromDhall b) => FromDhall (a -> b)+--+-- Thanks to currying, this instance works for functions of multiple simple+-- arguments:+--+-- >>> dhallAnd <- input auto "\\(x : Bool) -> \\(y : Bool) -> x && y" :: IO (Bool -> Bool -> Bool)+-- >>> dhallAnd True False+-- False+--+-- However, you can't convert anything more complex than that (like a polymorphic+-- or higher-order function).  You will need to apply those functions to their+-- arguments within Dhall before converting their result to a Haskell value.+--+-- Just like `FromDhall`, you can derive `ToDhall` for user-defined data types:+--+-- > {-# LANGUAGE DeriveAnyClass    #-}+-- > {-# LANGUAGE DeriveGeneric     #-}+-- > {-# LANGUAGE OverloadedStrings #-}+-- >+-- > module Main where+-- >+-- > import Dhall+-- >+-- > data Example0 = Example0 { foo :: Bool, bar :: Bool }+-- >     deriving (Generic, ToDhall)+-- >+-- > main = do+-- >     f <- input auto "\\(r : { foo : Bool, bar : Bool }) -> r.foo && r.bar"+-- >     print (f (Example0 { foo = True, bar = False }) :: Bool)+-- >     print (f (Example0 { foo = True, bar = True  }) :: Bool)+--+-- The above program prints:+--+-- > False+-- > True++-- $compiler+--+-- We can also test our @makeBools@ function directly from the command line.+-- This library comes with a command-line executable program named @dhall@ that+-- you can use to both type-check files and convert them to a normal form.  Our+-- compiler takes a program on standard input and then prints the program's type+-- to standard error followed by the program's normal form to standard output:+--+-- > $ dhall --annotate <<< './makeBools.dhall'+-- > (λ(n : Bool) → [ n, False, True, n ]) : ∀(n : Bool) → List Bool+--+-- The @dhall@ command emits Unicode output by default, but you can switch to+-- ASCII output using the @--ascii@ flag:+--+-- > $ dhall --annotate --ascii <<< './makeBools.dhall'+-- > (\(n : Bool) -> [ n, False, True, n ]) : forall (n : Bool) -> List Bool+--+-- The @--annotate@ flag adds a type signature to the output to let us know+-- what type the interpreter inferred for our expression.  The type signature+-- is @∀(n : Bool) → List Bool@ which says that @makeBools@ is a function of one+-- argument named @n@ that has type @Bool@ and the function returns a @List@ of+-- @Bool@s.  The @∀@ (U+2200) symbol is shorthand for the ASCII @forall@+-- keyword:+--+-- > ∀(x : a) → b         -- This type ...+-- >+-- > forall (x : a) -> b  -- ... is the same as this type+--+-- ... and Dhall's @forall@ keyword behaves the same way as Haskell's @forall@+-- keyword for input values that are @Type@s:+--+-- > forall (x : Type) -> b  -- This Dhall type ...+--+-- > forall x . b            -- ... is the same as this Haskell type+--+-- The part where Dhall differs from Haskell is that you can also use+-- @∀@/@forall@ to give names to non-@Type@ arguments (such as the first+-- argument to @makeBools@).+--+-- This expression is our program's normal form:+--+-- > λ(n : Bool) → [ n, False, True, n ]+--+-- ... and the interpreter was able to simplify our expression by noting that:+--+-- * @n && True  = n@+-- * @n && False = False@+-- * @n || True  = True@+-- * @n || False = n@+--+-- To apply a function to an argument you separate the function and argument by+-- whitespace (just like Haskell):+--+-- @f x@+--+-- You can read the above as \"apply the function @f@ to the argument @x@\".  This+-- means that we can \"apply\" our @./makeBools@ function to a @Bool@ argument+-- like this:+--+-- > $ dhall <<< './makeBools.dhall True'+-- > [True, False, True, True]+--+-- Remember that file paths are synonymous with their contents, so the above+-- code is exactly equivalent to:+--+-- > $ dhall <<< '(\(n : Bool) -> [n && True, n && False, n || True, n || False]) True'+-- > [True, False, True, True]+--+-- When you apply an anonymous function to an argument, you substitute the+-- \"bound variable" with the function's argument:+--+-- >    Bound variable+-- >    ⇩+-- > (\(n : Bool) -> ...) True+-- >                      ⇧+-- >                      Function argument+--+-- So in our above example, we would replace all occurrences of @n@ with @True@,+-- like this:+--+-- > -- If we replace all of these `n`s with `True` ...+-- > [n && True, n && False, n || True, n || False]+-- >+-- > -- ... then we get this:+-- > [True && True, True && False, True || True, True || False]+-- >+-- > -- ... which reduces to the following normal form:+-- > [True, False, True, True]+--+-- Now that we've verified that our function type checks and works, we can use+-- the same function within Haskell:+--+-- >>> input auto "./makeBools.dhall True" :: IO (Vector Bool)+-- [True,False,True,True]+--+-- __Exercise__: Create a file named @getFoo@ that is a function of the following+-- type:+--+-- > forall (r : { foo : Bool, bar : Text }) -> Bool+--+-- This function should take a single input argument named @r@ that is a record+-- with two fields.  The function should return the value of the @foo@ field.+--+-- __Exercise__: Use the @dhall@ command to infer the type of the function you+-- just created and verify that your function has the correct type+--+-- __Exercise__: Use the @dhall@ command to apply your function to a sample+-- record++-- $strings+-- Dhall supports ordinary string literals with Haskell-style escaping rules:+--+-- > $ dhall+-- > "Hello, \"world\"!"+-- > <Ctrl-D>+-- > "Hello, \"world\"!"+--+-- ... and Dhall also supports Nix-style multi-line string literals:+--+-- > $ dhall+-- > ''+-- >     #!/bin/bash+-- >+-- >     echo "Hi!"+-- > ''+-- > <Ctrl-D>+-- > "\n#!/bin/bash\n\necho \"Hi!\"\n"+--+-- These \"double single quote strings\" ignore all special characters, with one+-- exception: if you want to include a @''@ in the string, you will need to+-- escape it with a preceding @'@ (i.e. use @'''@ to insert @''@ into the final+-- string).+--+-- These strings also strip leading whitespace using the same rules as Nix.+-- Specifically: \"it strips from each line a number of spaces equal to the+-- minimal indentation of the string as a whole (disregarding the indentation+-- of empty lines).\"+--+-- You can also interpolate expressions into strings using @${...}@ syntax.  For+-- example:+--+-- > $ dhall+-- > let name = "John Doe"+-- > let age  = 21+-- > in  "My name is ${name} and my age is ${Natural/show age}"+-- > <Ctrl-D>+-- > "My name is John Doe and my age is 21"+--+-- Note that you can only interpolate expressions of type @Text@+--+-- If you need to insert a @"${"@ into a string without interpolation then use+-- @"''${"@ (same as Nix)+--+-- > ''+-- >     for file in *; do+-- >       echo "Found ''${file}"+-- >     done+-- > ''++-- $combine+--+-- You can combine two records, using either the @(//)@ operator or the+-- @(/\\)@ operator.+--+-- The @(//)@ operator (or @(⫽)@ U+2AFD) combines the fields of both records,+-- preferring fields from the right record if they share fields in common:+--+-- > $ dhall+-- > { foo = 1, bar = "ABC" } // { baz = True }+-- > <Ctrl-D>+-- > { bar = "ABC", baz = True, foo = 1 }+-- > $ dhall+-- > { foo = 1, bar = "ABC" } ⫽ { bar = True }  -- Fancy unicode+-- > <Ctrl-D>+-- > { bar = True, foo = 1 }+--+-- Note that the order of record fields does not matter.  The compiler+-- automatically sorts the fields.+--+-- If you need to set or add a deeply nested field you can use the @with@+-- keyword, like this:+--+-- > $ dhall <<< '{ x.y = 1 } with x.z = True'+-- > { x = { y = 1, z = True } }+--+-- > $ dhall <<< '{ x.y = 1 } with x.y = 2'+-- > { x.y = 2 }+--+-- The @with@ keyword is syntactic sugar for the @//@ operator which follows+-- these rules:+--+-- > -- Nested case+-- > record with k.ks… = value  ⇒  record // { k = record.k with ks… = value }+-- >+-- > -- Base case+-- > record with k = value      ⇒  record // { k = value }+--+-- The @(/\\)@ operator (or @(∧)@ U+2227) also lets you combine records, but+-- behaves differently if the records share fields in common.  The operator+-- combines shared fields recursively if they are both records:+--+-- > $ dhall+-- > { foo = { bar = True }, baz = "ABC" } /\ { foo = { qux = 1.0 } }+-- > <Ctrl-D>+-- > { baz = "ABC", foo = { bar = True, qux = 1.0 } }+--+-- ... but fails with a type error if either shared field is not a record:+--+-- > $ dhall+-- > { foo = 1, bar = "ABC" } /\ { foo = True }+-- > <Ctrl-D>+-- > Use "dhall --explain" for detailed errors+-- >+-- > Error: Field collision+-- >+-- > { foo = 1, bar = "ABC" } ∧ { foo = True }+-- >+-- > (input):1:1+--+-- __Exercise__: Combine any record with the empty record.  What do you expect+-- to happen?+--+-- You can analogously combine record types using the @//\\\\@ operator (or @(⩓)@ U+2A53):+--+-- > $ dhall+-- > { foo : Natural } //\\ { bar : Text }+-- > <Ctrl-D>+-- > { foo : Natural, bar : Text }+--+-- ... which behaves the exact same, except at the type level, meaning that the+-- operator descends recursively into record types:+--+-- > $ dhall+-- > { foo : { bar : Text } } //\\ { foo : { baz : Bool }, qux : Natural }+-- > <Ctrl-D>+-- > { foo : { bar : Text, baz : Bool }, qux : Natural }++-- $let+--+-- Dhall also supports @let@ expressions, which you can use to define+-- intermediate values in the course of a computation, like this:+--+-- > $ dhall+-- > let x = "ha" in x ++ x+-- > <Ctrl-D>+-- > "haha"+--+-- You can also annotate the types of values defined within a @let@ expression,+-- like this:+--+-- > $ dhall+-- > let x : Text = "ha" in x ++ x+-- > <Ctrl-D>+-- > "haha"+--+-- You need to nest @let@ expressions if you want to define more than one value+-- in this way:+--+-- > $ dhall+-- > let x = "Hello, "+-- > let y = "world!"+-- > in  x ++ y+-- > <Ctrl-D>+-- > "Hello, world!"+--+-- Dhall is whitespace-insensitive, so feel free to format things over multiple+-- lines or indent in any way that you please.+--+-- If you want to define a named function, just give a name to an anonymous+-- function:+--+-- > $ dhall+-- > let twice = \(x : Text) -> x ++ x in twice "ha"+-- > <Ctrl-D>+-- > "haha"+--+-- Unlike Haskell, Dhall does not support function arguments on the left-hand+-- side of the equals sign, so this will not work:+--+-- > $ dhall+-- > let twice (x : Text) = x ++ x in twice "ha"+-- > <Ctrl-D>+-- > Error: Invalid input+-- >+-- > (input):1:11:+-- >   |+-- > 1 | let twice (x : Text) = x ++ x in twice "ha"+-- >   |           ^+-- > unexpected '('+-- > expecting ':', '=', or the rest of label+--+-- The error message says that Dhall expected either a @(:)@ (i.e. the beginning+-- of a type annotation) or a @(=)@ (the beginning of the assignment) and not a+-- function argument.+--+-- You can also use @let@ expressions to rename imports, like this:+--+-- > $ dhall+-- > let not = https://prelude.dhall-lang.org/Bool/not+-- > in  not True+-- > <Ctrl-D>+-- > False+--+-- ... or to define synonyms for types:+--+-- > $ dhall <<< 'let Name : Type = Text in [ "John", "Mary" ] : List Name'+-- > List Text+-- >+-- > [ "John", "Mary" ]+--+-- __Exercise:__ What do you think the following code will normalize to?+--+-- > let x = 1+-- > let x = 2+-- > in  x+--+-- Test your guess using the @dhall@ compiler+--+-- __Exercise:__ Now try to guess what this code will normalize to:+--+-- > let x = "ha"+-- > let x = x ++ "ha"+-- > in  x+--+-- __Exercise:__ What about this code?+--+-- > let x = x ++ "ha"+-- > in  x++-- $defaults+--+-- For records with a large number of defaultable fields you can use the+-- @::@ operator to auto-complete a record.  For example:+--+-- > let greet =+-- >           \(args : { greeting : Text, name : Text })+-- >       ->  "${args.greeting}, ${args.name}!"+-- >+-- > let Greeting =+-- >       { Type = { greeting : Text, name : Text }+-- >       , default = { greeting = "Hello", name = "John" }+-- >       }+-- >+-- > in  ''+-- >     ${greet Greeting::{=}}+-- >     ${greet Greeting::{ greeting = "Hola" }}+-- >     ${greet Greeting::{ name = "Jane" }}+-- >     ${greet Greeting::{ greeting = "Hola", name = "Jane" }}+-- >     ''+--+-- This operator is syntactic sugar.  Specifically an expression of the form:+--+-- > T::r+--+-- ... is equivalent to:+--+-- > (T.default // r) : T.Type+--+-- So, for example:+--+-- > Greeting::{ greeting = "Hola" }+--+-- ... is the same thing as:+--+-- > (Greeting.default // { greeting = "Hola" }) : Greeting.Type+--+-- ... which is the same thing as:+--+-- > ({ greeting = "Hello", name = "John" } // { greeting = "Hola" }) : { greeting : Text, name : Text }+--+-- ... which is the same thing as:+--+-- > { greeting = "Hola", name = "John" }++-- $unions+--+-- A union is a value that can be one of many alternative types of values.  For+-- example, the following union type:+--+-- > < Left : Natural | Right : Bool >+--+-- ... represents a value that can be either a @Natural@ or a @Bool@ value.  If+-- you are familiar with Haskell these are exactly analogous to Haskell's+-- \"sum types\" and the above type is equivalent to @Either Natural Bool@.+--+-- Each alternative is associated with a tag that distinguishes that alternative+-- from other alternatives.  In the above example, the @Left@ tag is used for+-- the @Natural@ alternative and the @Right@ tag is used for the @Bool@+-- alternative.+--+-- You can specify the value of a union constructor like this:+--+-- > let Union = < Left : Natural | Right : Bool>+-- >+-- > in  [ Union.Left 0, Union.Right True ]+--+-- In other words, you can access a union constructor as a field of a union+-- type and use that constructor to wrap a value of a type appropriate for+-- that alternative.  In the above example, the @Left@ constructor can wrap+-- a @Natural@ value and the @Right@ constructor can wrap a @Bool@ value.  We+-- can also confirm that by inspecting their type:+--+-- > $ echo '< Left : Natural | Right : Bool>' > ./Union+--+-- > $ dhall --annotate <<< '(./Union).Left'+-- >   < Left : Natural | Right : Bool >.Left+-- > : ∀(Left : Natural) → < Left : Natural | Right : Bool >+--+-- > $ dhall --annotate <<< '(./Union).Right'+-- >   < Left : Natural | Right : Bool >.Right+-- > : ∀(Right : Bool) → < Left : Natural | Right : Bool >+--+-- In other words, the @Left@ constructor is a function from a @Natural@ to a+-- value of our @Union@ type and the @Right@ constructor is a separate function+-- from a @Bool@ to that same @Union@ type.+--+-- You can consume a union using the built-in @merge@ function.  For example,+-- suppose we want to convert our union to a @Bool@ but we want to behave+-- differently depending on whether or not the union is a @Natural@ wrapped in+-- the @Left@ constructor or a @Bool@ wrapped in the @Right@ constructor .  We+-- would write:+--+-- > $ cat > process <<EOF+-- >   \(union : < Left : Natural | Right : Bool >) ->+-- >     let handlers =+-- >             { Left  = Natural/even  -- Natural/even is a built-in function+-- >             , Right = \(b : Bool) -> b+-- >             }+-- > in  merge handlers union+-- > EOF+--+-- Now our @./process@ function can handle both alternatives:+--+-- > $ dhall <<< './process ((./Union).Left 3)'+-- > False+--+-- > $ dhall <<< './process ((./Union).Right True)'+-- > True+--+-- Every @merge@ has the following form:+--+-- > merge handlers union [ : type ]+--+-- ... where:+--+-- * @union@ is the union you want to consume+-- * @handlers@ is a record with one function per alternative of the union+-- * @type@ is an optional declared result type of the @merge@+--+-- The @merge@ function selects which function to apply from the record based on+-- which alternative the union selects:+--+-- > merge { Foo = f, ... } (< … >.Foo x) = f x+--+-- So, for example:+--+-- > merge { Left = Natural/even, Right = \(b : Bool) -> b } (< Left : Natural | Right : Bool >.Left 3)+-- >     = Natural/even 3+-- >     = False+--+-- ... and similarly:+--+-- > merge { Left = Natural/even, Right = \(b : Bool) -> b } (< Left : Natural | Right : Bool >.Right True)+-- >     = (\(b : Bool) -> b) True+-- >     = True+--+-- Notice that each handler has to return the same type of result (@Bool@ in+-- this case).+--+-- You can also store more than one value within alternatives using Dhall's+-- support for anonymous records.  You can nest an anonymous record within a+-- union such as in this type:+--+-- > < Empty : {} | Person : { name : Text, age : Natural } >+--+-- You can even go a step further and omit the type of an alternative if it+-- stores no data, like this:+--+-- > < Empty | Person : { name : Text, age : Natural } >+--+-- The above Dhall type resembles the following equivalent Haskell data type:+--+-- > data Example = Empty | Person { name :: Text, age :: Text }+--+-- Empty alternatives like @Empty@ require no argument:+--+-- > let Example = < Empty | Person : { name : Text, age : Natural } >+-- >+-- > in  [ Example.Empty  -- Note the absence of any argument to `Empty`+-- >     , Example.Person { name = "John", age = 23 }+-- >     , Example.Person { name = "Amy" , age = 25 }+-- >     ]+--+-- ... and when you @merge@ an empty alternative the correspond handler takes no+-- argument:+--+-- > \(x : < Empty | Person : { name : Text, age : Natural } >) ->+-- >   merge+-- >     { Empty = "Unknown"  -- Note the absence of an anonymous function+-- >+-- >     , Person =+-- >         \(person : { name : Text, age : Natural }) ->+-- >           "Name: ${person.name}, Age: ${Natural/show person.age}"+-- >     }+-- >     x+--+-- __Exercise__: Create a list of the following type with at least one element+-- per alternative:+--+-- > List < Left : Natural | Right : Double >++-- $polymorphic+--+-- The Dhall language supports defining polymorphic functions (a.k.a.+-- \"generic\" functions) that work on more than one type of value.  However,+-- Dhall differs from Haskell by not inferring the types of these polymorphic+-- functions.  Instead, you must be explicit about what type of value the+-- function is specialized to.+--+-- Take, for example, Haskell's identity function named @id@:+--+-- > id :: a -> a+-- > id = \x -> x+--+-- The identity function is polymorphic, meaning that `id` works on values of+-- different types:+--+-- >>> id 4+-- 4+-- >>> id True+-- True+--+-- The equivalent function in Dhall is:+--+-- > \(a : Type) -> \(x : a) -> x+--+-- Notice how this function takes two arguments instead of one.  The first+-- argument is the type of the second argument.+--+-- Let's illustrate how this works by actually using the above function:+--+-- > $ echo "\\(a : Type) -> \\(x : a) -> x" > id+--+-- Let's ask the interpreter for the type of this function:+-- the first line:+--+-- > $ dhall type <<< './id'+-- > ∀(a : Type) → ∀(x : a) → a+--+-- You can read the type @(∀(a : Type) → ∀(x : a) → a)@ as saying: \"This is the+-- type of a function whose first argument is named @a@ and is a @Type@.  The+-- second argument is named @x@ and has type @a@ (i.e. the value of the first+-- argument).  The result also has type @a@.\"+--+-- This means that the type of the second argument changes depending on what+-- type we provide for the first argument.  When we apply @./id@ to @Natural@,+-- we create a function that expects an @Natural@ argument:+--+-- > $ dhall type <<< './id Natural'+-- > ∀(x : Natural) → Natural+--+-- Similarly, when we apply @./id@ to @Bool@, we create a function that expects a+-- @Bool@ argument:+--+-- > $ dhall type <<< './id Bool'+-- > ∀(x : Bool) → Bool+--+-- We can then supply the final argument to each of those functions to show+-- that they both work on their respective types:+--+-- > $ dhall <<< './id Natural 4'+-- > 4+--+-- > $ dhall <<< './id Bool True'+-- > True+--+-- Built-in functions can also be polymorphic, too.  For example, we can ask+-- the compiler for the type of @List/reverse@, the function that reverses a+-- list:+--+-- > $ dhall --annotate+-- > List/reverse+-- > <Ctrl-D>+-- > List/reverse : ∀(a : Type) → List a → List a+--+-- The first argument to @List/reverse@ is the type of the list to reverse:+--+-- > $ dhall+-- > List/reverse Bool+-- > <Ctrl-D>+-- > List/reverse Bool : List Bool → List Bool+--+-- ... and the second argument is the list to reverse:+--+-- > $ dhall+-- > List/reverse Bool [True, False]+-- > <Ctrl-D>+-- > [False, True]+--+-- Note that the second argument has no name.  This type:+--+-- > ∀(a : Type) → List a → List a+--+-- ... is equivalent to this type:+--+-- > ∀(a : Type) → ∀(_ : List a) → List a+--+-- In other words, if you don't see the @∀@ symbol surrounding a function+-- argument type then that means that the name of the argument is @"_"@.  This+-- is true even for user-defined functions:+--+-- > $ dhall type <<< '\\(_ : Text) -> 1'+-- > Text → Natural+--+-- The type @Text → Natural@ is the same as @∀(_ : Text) → Natural@+--+-- __Exercise__ : Translate Haskell's `flip` function to Dhall++-- $total+--+-- Dhall is a total programming language, which means that Dhall is not+-- Turing-complete and evaluation of every Dhall program is guaranteed to+-- eventually halt.  There is no upper bound on how long the program might take+-- to evaluate, but the program is guaranteed to terminate in a finite amount of+-- time and not hang forever.+--+-- This guarantees that all Dhall programs can be safely reduced to a normal+-- form where as many functions have been evaluated as possible.  In fact, Dhall+-- expressions can be evaluated even if all function arguments haven't been fully+-- applied.  For example, the following program is an anonymous function:+--+-- > $ dhall+-- > \(n : Bool) -> 10 * 10+-- > <Ctrl-D>+-- > λ(n : Bool) → 100+--+-- ... and even though the function is still missing the first argument named+-- @n@ the compiler is smart enough to evaluate the body of the anonymous+-- function ahead of time before the function has even been invoked.+--+-- We can use the @map@ function from the Prelude to illustrate an even more+-- complex example:+--+-- > $ dhall+-- > let List/map = https://prelude.dhall-lang.org/List/map+-- > in  \(f : Natural → Natural) -> List/map Natural Natural f [1, 2, 3]+-- > <Ctrl-D>+-- > λ(f : Natural → Natural) → [f 1, f 2, f 3]+--+-- Dhall can apply our function to each element of the list even before we specify+-- which function to apply.+--+-- The language will also never crash or throw any exceptions.  Every+-- computation will succeed and produce something, even if the result might be+-- an @Optional@ value:+--+-- > $ dhall <<< 'List/head Natural ([] : List Natural)'+-- > None Natural+--+-- __Exercise__: The Dhall Prelude provides a @replicate@ function which you can+-- find here:+--+-- <https://prelude.dhall-lang.org/List/replicate>+--+-- Test what the following Dhall expression normalizes to:+--+-- > let replicate = https://prelude.dhall-lang.org/List/replicate+-- > in  replicate 10+--+-- __Exercise__: If you have a lot of spare time, try to \"break the compiler\"+-- by finding an input expression that crashes or loops forever (and file a bug+-- report if you succeed).++-- $assertions+--+-- You can add compile-time assertions which you can use to add tests to your+-- code.  For example, we can add some tests to our @not@ function like this:+--+-- > let not+-- >     : Bool -> Bool+-- >     = \(b : Bool) -> b == False+-- >+-- > let example0 = assert : not False === True+-- >+-- > let example1 = assert : not True === False+-- >+-- > in  not+--+-- The expression @assert : not False == True@ is a type-checking assertion+-- that two expressions have the same normal form.  If the two expressions differ+-- then type-checking rejects the code.+--+-- For example, suppose that we change the example to add an incorrect assertion:+--+-- > -- ./test.dhall+-- >+-- > let not+-- >     : Bool -> Bool+-- >     = \(b : Bool) -> b == False+-- >+-- > let example0 = assert : not False === True+-- >+-- > let example1 = assert : not True === True  -- Oops!+-- >+-- > in  not+--+-- The type-checker then rejects the assertion with the following error message:+--+-- > $ dhall <<< './test.dhall'+-- >+-- > ↳ ./test.dhall+-- >+-- > Error: Assertion failed+-- >+-- > - False+-- > + True+-- >+-- > 7│                assert : not True === True -- Oops!+-- > 8│+-- >+-- > ./test.dhall:7:16+-- >+-- > 1│ ./test.dhall+-- >+-- > (input):1:1+--+-- You can compare expressions that contain variables, too, which is equivalent+-- to symbolic reasoning:+--+-- > $ dhall <<< '\(n : Natural) -> assert : n === (n + 0)'+-- > λ(n : Natural) → assert : n ≡ n+--+-- Dhall accepts this because the language has built-in support for normalizing+-- @n + 0@ to @n@, so both sides of the comparison normalize to the same value:+-- @n@.+--+-- Note that this sort of symbolic reasoning is limited and can only detect+-- equality of normal forms.  Some equivalent expressions will be rejected+-- if they don't share the same normal form, such as these:+--+-- > $ dhall <<< '\(n : Natural) -> assert : Natural/even (n + n) === True'+-- >+-- > Use "dhall --explain" for detailed errors+-- >+-- > n : Natural+-- >+-- > Error: Assertion failed+-- >+-- > - … …+-- > + True+-- >+-- > 1│                   assert : Natural/even (n + n) === True+-- >+-- > (input):1:19+--+-- Here the interpreter is not smart enough to simplify @Natural/even (n + n)@+-- to @True@ so the assertion fails.+--+-- If you prefer to use Unicode, then the Unicode equivalent of @===@ is @≡@+-- (U+2261).++-- $headers+--+-- Sometimes you would like to provide additional request headers when importing+-- Dhall expressions from URLs.  For example, you might want to provide an+-- authorization header or specify the expected content type.+--+-- Dhall URL imports let you add or modify request headers with the @using@+-- keyword:+--+-- > https://example.com/example.dhall using ./headers+--+-- ... where you can replace @./headers@ with any import that points to a Dhall+-- expression of the following type:+--+-- > List { header : Text, value : Text }+--+-- For example, if you needed to specify the content type correctly in order to+-- download the file, then your @./headers@ file might look like this:+--+-- > $ cat headers+-- > [ { header = "Accept", value = "application/dhall" } ]+--+-- ... or if you needed to provide an authorization token to access a private+-- GitHub repository, then your headers could look like this:+--+-- > [ { header = "Authorization", value = "token ${env:GITHUB_TOKEN as Text}" } ]+--+-- This would read your GitHub API token from the @GITHUB_TOKEN@ environment+-- variable and supply that token in the authorization header.+--+-- You cannot inline the headers within the same file as the URL.  You must+-- provide them as a separate import.  That means that this is /not/ legal code:+--+-- > http://example.com/example.dhall using [ { header = "Accept", value = "application/dhall" } ]  -- NOT legal+--+-- Dhall will forward imports if you import an expression from a URL that+-- contains a relative import.  For example, if you import an expression like+-- this:+--+-- > http://example.com/example.dhall using ./headers+--+-- ... and @http:\/\/example.com/example.dhall@ contains a relative import of @./foo@+-- then Dhall will import @http:\/\/example.com/foo@ using the same @./headers@ file.++-- $integrity+--+-- Sometimes you want to use share code while still ensuring that the imported+-- value never changes and can't be corrupted by a malicious attacker.  Dhall+-- provides built-in support for hashing imported values to verify that their+-- value never changes+--+-- For example, suppose you save the following two files:+--+-- > $ cat ./foo+-- > ./bar sha256:d60d8415e36e86dae7f42933d3b0c4fe3ca238f057fba206c7e9fbf5d784fe15+--+-- > $ cat ./bar+-- > ./baz+--+-- > $ cat ./baz+-- > 1+--+-- The first file named @./foo@ contains an example of an integrity check.  You+-- can add @sha256:XXX@ after any import (such as after @./bar@), where @XXX@ is+-- an expected 64-character @sha256@ hash of the Dhall value.  To be precise,+-- the hash represents a @sha256@ hash of the UTF-8 encoding of a canonical text+-- representation of the fully resolved and normalized abstract syntax tree of+-- the imported expression.+--+-- Dhall will verify that the expected hash matches the actual hash of the+-- imported Dhall value and reject the import if there is a hash mismatch:+--+-- > $ dhall <<< './foo'+-- > Natural+-- >+-- > 1+--+-- Any import protected by a semantic integrity check is automatically cached+-- locally underneath either @~\/.cache\/dhall\/1220${HASH}@ or+-- @${XDG_CACHE_HOME}\/dhall/1220${HASH}@ if you define the @XDG_CACHE_HOME@+-- environment variable.+--+-- For example, after you import @./foo@ the contents of `./bar` are locally+-- cached in a fully-evaluated and binary-encoded form which you can inspect by+-- running:+--+-- > $ dhall decode < ~/.cache/dhall/1220d60d8415e36e86dae7f42933d3b0c4fe3ca238f057fba206c7e9fbf5d784fe15+-- > 1+--+-- Subsequent attempts to resolve the same import will automatically retrieve+-- the import from the cache.  This matters less for local imports, but comes in+-- handy for remote imports to avoid redownloading them.+--+-- The local cache takes precedence when resolving imports, so changing the+-- original import afterwards will have no affect until you update the hash.+-- From Dhall's point of view, the hash is the true address and the file path+-- is just a suggestion for how to obtain the import if it's not already cached.+--+-- You can disable the cache by setting @XDG_CACHE_HOME@ to `/var/empty` (an+-- empty and unwritable directory), like this:+--+-- > $ XDG_CACHE_HOME=/var/empty dhall <<< './foo'+-- > Natural+-- >+-- > 1+--+-- We'll use this trick to test changes to the protected import in the following+-- examples.+--+-- Now, suppose you add a comment to the @./bar@ file:+--+-- > $ cat ./bar+-- > -- This comment does not change the hash+-- > ./baz+--+-- ... then @./foo@ will still successfully import @./bar@ because the hash+-- only depends on the normalized value and does not depend on meaningless+-- changes to whitespace or comments:+--+-- > $ XDG_CACHE_HOME=/var/empty dhall <<< './foo'  # This still succeeds+-- > Natural+-- >+-- > 1+--+-- You can compute the Hash for any import by using the hash subcommand+-- of this package.  For example:+--+-- > $ dhall hash <<< './bar'+-- > sha256:d60d8415e36e86dae7f42933d3b0c4fe3ca238f057fba206c7e9fbf5d784fe15+--+-- Now suppose that you actually change the value of the @./baz@ file:+--+-- > $ cat ./baz+-- > 2+--+-- ... then the @./foo@ file will fail to import @./bar@, even though the+-- text of the @./bar@ file technically never changed:+--+-- > XDG_CACHE_HOME=/var/empty dhall <<< './foo'+-- >+-- > Error: Import integrity check failed+-- >+-- > Expected hash:+-- >+-- > ↳ d60d8415e36e86dae7f42933d3b0c4fe3ca238f057fba206c7e9fbf5d784fe15+-- >+-- > Actual hash:+-- >+-- > ↳ 4caf97e8c445d4d4b5c5b992973e098ed4ae88a355915f5a59db640a589bc9cb+--+-- This is because the @./bar@ file now represents a new value (@2@ instead of+-- @1@), even though the text of the @./bar@ file is still the same.  Since the+-- value changed the hash must change as well.  However, we could change @./baz@+-- to:+--+-- > $ cat baz+-- > if True then 1 else 2+--+-- ... and the import would now succeed again because the final result is @1@.+--+-- The integrity hash ensures that your import's final meaning can never change,+-- so an attacker can never compromise an imported value protected by a hash+-- unless they can break SHA-256 encryption.  The hash not only protects the+-- file that you immediately import, but also protects every transitive import+-- as well.+--+-- You can also safely refactor your imported dependencies knowing that the+-- refactor will not change your hash so long as your refactor is+-- behavior-preserving.  This provides an easy way to detect refactoring errors+-- that you might accidentally introduce.  The hash not only protects you+-- from attackers, but also protects against human error, too!+--+-- If you have a file which either doesn't already use hashed imports,+-- or you changed some of the imports and want to update the hashes you can use the+-- freeze command to either add or update hashes:+--+-- > $ cat foo.dhall+-- > let replicate = https://prelude.dhall-lang.org/List/replicate+-- > in  replicate 5+-- > $+-- > $ dhall freeze ./foo.dhall+-- > $ cat ./foo.dhall+-- > let replicate =+-- >       https://prelude.dhall-lang.org/List/replicate sha256:d4250b45278f2d692302489ac3e78280acb238d27541c837ce46911ff3baa347+-- >+-- > in  replicate 5++-- $rawText+--+-- Sometimes you want to import the contents of a raw text file as a Dhall+-- value of type `Dhall.Syntax.Text`.  For example, one of the fields of a+-- record might be the contents of a software license:+--+-- > { package = "dhall"+-- > , author  = "Gabriella Gonzalez"+-- > , license = ./LICENSE+-- > }+--+-- Normally if you wanted to import a text file you would need to wrap the+-- contents of the file in double single-quotes, like this:+--+-- > $ cat LICENSE+-- > ''+-- > Copyright (c) 2017 Gabriella Gonzalez+-- > All rights reserved.+-- >+-- > ...+-- > (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+-- > SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+-- > ''+--+-- ... which does not work well if you need to reuse the same text file for+-- other programs+--+-- However, Dhall supports importing a raw text file by adding @as Text@ to the+-- end of the import, like this:+--+-- > { package = "dhall"+-- > , author  = "Gabriella Gonzalez"+-- > , license = ./LICENSE as Text+-- > }+--+-- ... and then you can use the original text file unmodified:+--+-- > $ cat LICENSE+-- > Copyright (c) 2017 Gabriella Gonzalez+-- > All rights reserved.+-- >+-- > ...+-- > (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+-- > SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.++-- $format+--+-- A format subcommand is also available that you can use to+-- automatically format Dhall expressions.  For example, we can take the+-- following unformatted Dhall expression:+--+-- > $ cat ./unformatted+-- > λ(a : Type) → λ(kvss : List (List { index : Natural, value : a })) →+-- > List/build { index : Natural, value : a } (λ(list : Type) → λ(cons : {+-- > index : Natural, value : a } → list → list) → λ(nil : list) →+-- > (List/fold (List { index : Natural, value : a }) kvss { count : Natural, diff :+-- > Natural → list } (λ(kvs : List { index : Natural, value : a }) → λ(y : {+-- > count : Natural, diff : Natural → list }) → { count = y.count + List/length+-- > { index : Natural, value : a } kvs, diff = λ(n : Natural) → List/fold {+-- > index : Natural, value : a } kvs list (λ(kvOld : { index : Natural, value : a+-- > }) → λ(z : list) → cons { index = kvOld.index + n, value = kvOld.value }+-- > z) (y.diff (n + List/length { index : Natural, value : a } kvs)) }) { count =+-- > 0, diff = λ(_ : Natural) → nil }).diff 0)+--+-- ... and run the expression through the formatter:+--+-- > $ dhall format < ./unformatted+-- > λ(a : Type) →+-- > λ(kvss : List (List { index : Natural, value : a })) →+-- >   List/build+-- >     { index : Natural, value : a }+-- >     ( λ(list : Type) →+-- >       λ(cons : { index : Natural, value : a } → list → list) →+-- >       λ(nil : list) →+-- >         ( List/fold+-- >             (List { index : Natural, value : a })+-- >             kvss+-- >             { count : Natural, diff : Natural → list }+-- >             ( λ(kvs : List { index : Natural, value : a }) →+-- >               λ(y : { count : Natural, diff : Natural → list }) →+-- >                 { count =+-- >                     y.count + List/length { index : Natural, value : a } kvs+-- >                 , diff =+-- >                     λ(n : Natural) →+-- >                       List/fold+-- >                         { index : Natural, value : a }+-- >                         kvs+-- >                         list+-- >                         ( λ(kvOld : { index : Natural, value : a }) →+-- >                           λ(z : list) →+-- >                             cons+-- >                               { index = kvOld.index + n, value = kvOld.value }+-- >                               z+-- >                         )+-- >                         ( y.diff+-- >                             (n + List/length { index : Natural, value : a } kvs)+-- >                         )+-- >                 }+-- >             )+-- >             { count = 0, diff = λ(_ : Natural) → nil }+-- >         ).diff+-- >           0+-- >     )+--+-- The executable formats expressions without resolving, type-checking, or+-- normalizing them:+--+-- > $ dhall format+-- > let replicate = https://prelude.dhall-lang.org/List/replicate+-- > in replicate 5 (List (List Natural)) (replicate 5 (List Natural) (replicate 5 Natural 1))+-- > <Ctrl-D>+-- > let replicate = https://prelude.dhall-lang.org/List/replicate+-- >+-- > in  replicate+-- >       5+-- >       (List (List Natural))+-- >       (replicate 5 (List Natural) (replicate 5 Natural 1))+--+-- You can also use the formatter to modify files in place:+--+-- > $ dhall format ./unformatted+--+-- Carefully note that the code formatter does not preserve all comments.+-- Currently, the formatter only preserves two types of comments:+--+-- * Leading comments at the beginning of the file+-- * Comments within a @let@ binding+--+-- For example:+--+-- > $ dhall format+-- > {- This comment will be preserved by the formatter -}+-- > -- ... and this comment will be preserved, too+-- > {- This comment will *NOT* be preserved -} 1+-- > -- ... and this comment will also *NOT* be preserved+-- > <Ctrl-D>+-- > {- This comment will be preserved by the formatter -}+-- > -- ... and this comment will be preserved, too+-- > 1+--+-- Also:+--+-- > let {- This comment will be preserved -}+-- >     x {- This comment will also be preserved-} =+-- >     {- ... and this one will be preserved, too -}+-- >       1+-- >+-- > in  x+--+-- Note that you do not need to format the output of the+-- @dhall@ interpreter.  The interpreter already automatically formats+-- multi-line expressions, too:+--+-- > $ dhall+-- > let replicate = https://prelude.dhall-lang.org/List/replicate+-- > in replicate 5 (List (List Natural)) (replicate 5 (List Natural) (replicate 5 Natural 1))+-- > <Ctrl-D>+-- > [ [ [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   ]+-- > , [ [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   ]+-- > , [ [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   ]+-- > , [ [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   ]+-- > , [ [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   , [ 1, 1, 1, 1, 1 ]+-- >   ]+-- > ]++-- $builtins+--+-- Dhall is a restricted programming language that only supports simple built-in+-- functions and operators.  If you want to do anything fancier you will need to+-- load your data into Haskell for further processing+--+-- This section covers types, functions, and operators that are built into the+-- language, meaning that you do not need to import any code to use them.+-- Additionally, Dhall also comes with a Prelude (covered in the next section)+-- hosted online that contains functions derived from these base utilities.  The+-- Prelude also re-exports all built-in functions for people who prefer+-- consistency.+--+-- The language provides built-in support for the following primitive types:+--+-- * @Bool@ values+-- * @Natural@ values+-- * @Integer@ values+-- * @Double@ values+-- * @Text@ values+--+-- ... as well as support for the following derived types:+--+-- * @List@s of values+-- * @Optional@ values+-- * Anonymous records+-- * Anonymous unions+--+-- You can find an up-to-date list of available built-in functions and operators+-- here:+--+-- <https://docs.dhall-lang.org/references/Built-in-types.html>++-- $caveats+--+-- Dhall differs in a few important ways from other programming languages, so+-- you should keep the following caveats in mind:+--+-- First, Dhall only supports addition and multiplication on @Natural@ numbers+-- (i.e. non-negative integers), which are not the same type of number as+-- @Integer@s (which can be negative).  An @Integer@ number is a number prefixed+-- with either a @+@ or @-@ symbol whereas a @Natural@ number has no leading+-- sign.  If you try to add or multiply two @Integer@s you will get a type+-- error:+--+-- > $ dhall+-- > +2 + +2+-- > <Ctrl-D>+-- > Use "dhall --explain" for detailed errors+-- >+-- > Error: ❰+❱ only works on ❰Natural❱s+-- >+-- > +2 + +2+-- >+-- > (input):1:1+--+-- There are no built-in functions for @Integer@ arithmetic; however, conversion+-- to and from @Natural@s is possible usinng @Integer/clamp@, @Integer/negate@+-- and @Natural/toInteger@.+--+-- For @Double@s the situation is even more extreme: there are no built-in+-- functions other than @Double/show@. As far as the language is concerned they+-- are opaque values that can only be shuffled around but not used in any+-- meaningful way until they have been loaded into Haskell.+--+-- Second, the equality @(==)@ and inequality @(!=)@ operators only work on+-- @Bool@s.  You cannot test any other types of values for equality.+--+-- However, you can extend the language with your own built-ins using the+-- Haskell API, as described in the next section.++-- $extending+--+-- You can use the Haskell API to extend the Dhall configuration language with+-- new built-in functions.  This section contains a simple Haskell recipe to add+-- a new @Natural/equal@ built-in function of type:+--+-- > Natural/equal : Natural -> Natural -> Bool+--+-- To do so, we:+--+-- * extend the type-checking context to include the type of @Natural/equal@+-- * extend the normalizer to evaluate all occurrences of @Natural/equal@+--+-- ... like this:+--+-- > -- example.hs+-- >+-- > {-# LANGUAGE OverloadedStrings #-}+-- >+-- > module Main where+-- >+-- > import Dhall.Core (Expr(..), ReifiedNormalizer(..))+-- >+-- > import qualified Data.Text.IO+-- > import qualified Dhall+-- > import qualified Dhall.Context+-- > import qualified Lens.Family   as Lens+-- >+-- > main :: IO ()+-- > main = do+-- >     text <- Data.Text.IO.getContents+-- >+-- >     let startingContext = transform Dhall.Context.empty+-- >           where+-- >             transform = Dhall.Context.insert "Natural/equal" naturalEqualType+-- >+-- >             naturalEqualType =+-- >                 Pi "_" Natural (Pi "_" Natural Bool)+-- >+-- >     let normalizer (App (App (Var "Natural/equal") (NaturalLit x)) (NaturalLit y)) =+-- >             Just (BoolLit (x == y))+-- >         normalizer _ =+-- >             Nothing+-- >+-- >     let inputSettings = transform Dhall.defaultInputSettings+-- >           where+-- >             transform =+-- >                   Lens.set Dhall.normalizer      (Just (ReifiedNormalizer (pure . normalizer)))+-- >                 . Lens.set Dhall.startingContext startingContext+-- >+-- >     x <- Dhall.inputWithSettings inputSettings Dhall.auto text+-- >+-- >     Data.Text.IO.putStrLn x+--+-- Here is an example use of the above program:+--+-- > $ ./example <<< 'if Natural/equal 2 (1 + 1) then "Equal" else "Not equal"'+-- > Equal+--+-- Note that existing Dhall tools that type-check expressions will reject+-- expressions containing unexpected free variable such as @Natural/equal@:+--+-- > $ dhall <<< 'Natural/equal 2 (1 + 1)'+-- >+-- > Use "dhall --explain" for detailed errors+-- >+-- > Error: Unbound variable+-- >+-- > Natural/equal+-- >+-- > (input):1:1+--+-- You will need to either:+--+-- * create your own parallel versions of these tools, or:+-- * < https://github.com/dhall-lang/dhall-lang/blob/master/.github/CONTRIBUTING.md#how-do-i-change-the-language try to upstream your built-ins into the language>+--+-- The general guidelines for adding new built-ins to the language are:+--+-- * Keep built-ins easy to implement across language bindings+-- * Prefer general purpose built-ins or built-ins appropriate for the task of program configuration+-- * Design built-ins to catch errors as early as possible (i.e. when type-checking the configuration)++-- $substitutions+--+-- Substitutions are another way to extend the language.+--+-- Suppose we have the following Haskell datatype:+--+-- > data Result = Failure Integer | Success String+-- >     deriving (Eq, Generic, Show)+-- >+-- > instance FromDhall Result+--+-- We can use it in Dhall like that:+--+-- > -- example.dhall+-- >+-- > let Result = < Failure : Integer | Success : Text >+-- > in Result.Failure +1+--+-- Right now it is quite easy to keep these two definitions (the one in Haskell source and the one in the Dhall file) synchronized:+-- If we implement a new feature in the Haskell source we update the corresponding type in the Dhall file.+-- But what happens if our application is growing and our Result type contains e.g. 10 unions with possible types embedded in it?+--+-- We can override the interpreter's @evaluateSettings@ with a custom set of+-- substitutions, like this:+--+-- > {-# LANGUAGE OverloadedStrings #-}+-- >+-- > myexample :: IO Result+-- > myexample = let+-- >    evaluateSettings = Lens.over Dhall.substitutions (Dhall.Map.insert "Result" resultType) Dhall.defaultEvaluateSettings+-- >    in Dhall.inputFileWithSettings evaluateSettings resultDecoder "example.dhall"+--+-- Substitutions are a simple 'Dhall.Map.Map' mapping variables to expressions. The application of these substitutions reflect the order of the insertions in the substitution map:+--+-- > {-# LANGUAGE OverloadedStrings #-}+-- >+-- > substitute (Dhall.Core.Var "Foo") (Dhall.Map.fromList [("Foo", Dhall.Core.Var "Bar"), ("Bar", Dhall.Core.BoolLit True)])+--+-- results in @Dhall.Core.Var \"Baz\"@ since we first substitute \"Foo\" with \"Bar\" and then the resulting \"Bar\" with the final @True@.+--+-- Notable differences to the other extensions of the builtin language:+--+--  * This approach works well with the inputFile/inputFileWithSettings functions while the let-wrapping will not.+--+--  * In contrast to the custom built-ins described above substitutions are made BEFORE the type-checking.++-- $prelude+--+-- There is also a Prelude available at:+--+-- <https://prelude.dhall-lang.org>+--+-- If you visit the above link you can browse the Prelude, which has a few+-- subdirectories.  For example, the @Bool@ subdirectory has a @not@ file, which+-- you can reference using this URL:+--+-- <https://prelude.dhall-lang.org/Bool/not>+--+-- The @not@ function is just a UTF8-encoded text file hosted online with the+-- following contents+--+-- > $ dhall <<< 'https://prelude.dhall-lang.org/Bool/not as Text'+-- > ''+-- > {-+-- > Flip the value of a Bool+-- > -}+-- > let not : Bool → Bool = λ(b : Bool) → b == False+-- >+-- > let example0 = assert : not True ≡ False+-- >+-- > let example1 = assert : not False ≡ True+-- >+-- > in  not+-- > ''+--+-- The file could have been much shorter, like this:+--+-- > λ(b : Bool) → b == False+--+-- ... but all the functions exported from the Prelude try to be as+-- self-documenting as possible by including:+--+-- * the name of the function+-- * the type of the function+-- * documentation+-- * tests+--+-- The performance penalty for adding these helpful features is negligible,+-- especially if you protect the import with a semantic integrity check because+-- then the import would be cached compactly as @λ(_ : Bool) → _ == False@.+--+-- You can use this @not@ function either directly:+--+-- > $ dhall+-- > https://prelude.dhall-lang.org/Bool/not True+-- > <Ctrl-D>+-- > False+--+-- ... or assign the URL to a shorter name:+--+-- > $ dhall+-- > let Bool/not = https://prelude.dhall-lang.org/Bool/not+-- > in  Bool/not True+-- > <Ctrl-D>+-- > False+--+-- Some functions in the Prelude just re-export built-in functions for+-- consistency and documentation, such as @Prelude\/Natural\/even@, which+-- re-exports the built-in @Natural/even@ function:+--+-- > $ dhall <<< 'https://prelude.dhall-lang.org/Natural/even as Text'+-- > ''+-- > {-+-- > Returns `True` if a number if even and returns `False` otherwise+-- > -}+-- > let even : Natural → Bool = Natural/even+-- >+-- > let example0 = assert : even 3 ≡ False+-- >+-- > let example1 = assert : even 0 ≡ True+-- >+-- > in  even+-- > ''+--+-- You can also clone the Prelude locally to your filesystem if you prefer+-- using `git clone`, like this:+--+-- > $ git clone https://github.com/dhall-lang/dhall-lang.git+-- > $ tree dhall-lang/Prelude+-- > dhall-lang/Prelude+-- > ├── Bool+-- > │   ├── and+-- > │   ├── build+-- > │   ├── even+-- > │   ├── fold+-- > │   ├── not+-- > │   ├── odd+-- > │   ├── or+-- > │   ├── package.dhall+-- > │   └── show+-- > ├── Double+-- > │   ├── package.dhall+-- > │   └── show+-- > ├── Function+-- > │   ├── compose+-- > │   └── package.dhall+-- > ├── Integer+-- > │   ├── package.dhall+-- > │   ├── show+-- > │   └── toDouble+-- > ├── JSON+-- > │   ├── Nesting+-- > │   ├── Tagged+-- > │   ├── Type+-- > │   ├── array+-- > │   ├── bool+-- > │   ├── keyText+-- > │   ├── keyValue+-- > │   ├── null+-- > │   ├── number+-- > │   ├── object+-- > │   ├── package.dhall+-- > │   ├── render+-- > │   └── string+-- > ├── List+-- > │   ├── all+-- > │   ├── any+-- > │   ├── build+-- > │   ├── concat+-- > │   ├── concatMap+-- > │   ├── default+-- > │   ├── empty+-- > │   ├── filter+-- > │   ├── fold+-- > │   ├── generate+-- > │   ├── head+-- > │   ├── indexed+-- > │   ├── iterate+-- > │   ├── last+-- > │   ├── length+-- > │   ├── map+-- > │   ├── null+-- > │   ├── package.dhall+-- > │   ├── replicate+-- > │   ├── reverse+-- > │   ├── shifted+-- > │   └── unzip+-- > ├── Location+-- > │   ├── Type+-- > │   └── package.dhall+-- > ├── Map+-- > │   ├── Entry+-- > │   ├── Type+-- > │   ├── empty+-- > │   ├── keyText+-- > │   ├── keyValue+-- > │   ├── keys+-- > │   ├── map+-- > │   ├── package.dhall+-- > │   └── values+-- > ├── Monoid+-- > ├── Natural+-- > │   ├── build+-- > │   ├── enumerate+-- > │   ├── equal+-- > │   ├── even+-- > │   ├── fold+-- > │   ├── greaterThan+-- > │   ├── greaterThanEqual+-- > │   ├── isZero+-- > │   ├── lessThan+-- > │   ├── lessThanEqual+-- > │   ├── odd+-- > │   ├── package.dhall+-- > │   ├── product+-- > │   ├── show+-- > │   ├── subtract+-- > │   ├── sum+-- > │   ├── toDouble+-- > │   └── toInteger+-- > ├── Optional+-- > │   ├── all+-- > │   ├── any+-- > │   ├── build+-- > │   ├── concat+-- > │   ├── default+-- > │   ├── filter+-- > │   ├── fold+-- > │   ├── head+-- > │   ├── last+-- > │   ├── length+-- > │   ├── map+-- > │   ├── null+-- > │   ├── package.dhall+-- > │   ├── toList+-- > │   └── unzip+-- > ├── Text+-- > │   ├── concat+-- > │   ├── concatMap+-- > │   ├── concatMapSep+-- > │   ├── concatSep+-- > │   ├── default+-- > │   ├── defaultMap+-- > │   ├── package.dhall+-- > │   └── show+-- > ├── XML+-- > │   ├── Type+-- > │   ├── attribute+-- > │   ├── element+-- > │   ├── emptyAttributes+-- > │   ├── leaf+-- > │   ├── package.dhall+-- > │   ├── render+-- > │   └── text+-- > └── package.dhall+--+-- Browse the Prelude online to learn more by seeing what functions are+-- available and reading their inline documentation:+--+-- <https://prelude.dhall-lang.org>+--+-- __Exercise__: Try to use a new Prelude function that has not been covered+-- previously in this tutorial+--+-- You can also import the entire Prelude as a single large record for+-- convenience:+--+-- > $ dhall+-- > let Prelude = https://prelude.dhall-lang.org/package.dhall+-- >+-- > in  \(x : Text) ->+-- >       Prelude.List.length Text (Prelude.List.replicate 10 Text x)+-- > <Ctrl-D>+-- > ∀(x : Text) → Natural+-- >+-- > λ(x : Text) → 10+--+-- The organization of the package mirrors the layout of the Prelude, meaning+-- that every directory is stored as a record whose children are the fields of+-- that record.+--+-- __Exercise__: Browse the Prelude by running:+--+-- > $ dhall <<< 'https://prelude.dhall-lang.org/package.dhall'++-- $limitations+-- #limitations#+--+-- `FromDhall` has a limitiation: It won't work for recursive types.+-- If you instantiate these using their Generic instance you end up with one of+-- the following two cases:+--+-- If the type appears in it's own definition like+--+-- > data Foo = Foo Foo+-- >     deriving Generic+-- >+-- > instance FromDhall Foo+--+-- the resulting Decoder will throw an exception /ON USAGE/.+-- However, if the recursion is indirect like+--+-- > data Foo = Foo Bar+-- >     deriving Generic+-- >+-- > instance FromDhall Foo+-- >+-- > data Bar = Bar Foo+-- >     deriving Generic+-- >+-- > instance FromDhall Bar+--+-- the resulting Decoder will __NOT TERMINATE__ /ON USAGE/.++-- $conclusion+--+-- By this point you should be able to use the Dhall configuration language to+-- author, import, and program configuration files.  If you run into any issues+-- you can report them at:+--+-- <https://github.com/dhall-lang/dhall-haskell/issues>+--+-- Also, you might want to check out the+-- <https://docs.dhall-lang.org/tutorials/Language-Tour.html Language Tour>, a+-- more comprehensive tour of Dhall which may cover features missing from this+-- Haskell tutorial.+--+-- You can also request features, support, or documentation improvements on the+-- above issue tracker.+--+-- If you would like to contribute to the Dhall project you can try to port+-- Dhall to languages that do not yet have Dhall integrations so that Dhall configuration files+-- can be read into those languages, too.++-- $faq+--+-- <https://docs.dhall-lang.org/howtos/FAQ.html>
src/Dhall/TypeCheck.hs view
@@ -1,3926 +1,4851 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE OverloadedStrings  #-}-{-# LANGUAGE RankNTypes         #-}-{-# LANGUAGE RecordWildCards    #-}-{-# OPTIONS_GHC -Wall #-}---- | This module contains the logic for type checking Dhall code--module Dhall.TypeCheck (-    -- * Type-checking-      typeWith-    , typeOf-    , typeWithA-    , checkContext--    -- * Types-    , Typer-    , X(..)-    , TypeError(..)-    , DetailedTypeError(..)-    , TypeMessage(..)-    ) where--import Control.Applicative (empty)-import Control.Exception (Exception)-import Data.Data (Data(..))-import Data.Foldable (forM_, toList)-import Data.List.NonEmpty (NonEmpty(..))-import Data.Monoid (First(..))-import Data.Sequence (Seq, ViewL(..))-import Data.Semigroup (Semigroup(..))-import Data.Set (Set)-import Data.Text (Text)-import Data.Text.Prettyprint.Doc (Doc, Pretty(..))-import Data.Traversable (forM)-import Data.Typeable (Typeable)-import Dhall.Binary (FromTerm(..), ToTerm(..))-import Dhall.Core (Binding(..), Const(..), Chunks(..), Expr(..), Var(..))-import Dhall.Context (Context)-import Dhall.Pretty (Ann, layoutOpts)--import qualified Data.Foldable-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 Dhall.Context-import qualified Dhall.Core-import qualified Dhall.Diff-import qualified Dhall.Map-import qualified Dhall.Set-import qualified Dhall.Pretty.Internal-import qualified Dhall.Util--traverseWithIndex_ :: Applicative f => (Int -> a -> f b) -> Seq a -> f ()-traverseWithIndex_ k xs =-    Data.Foldable.sequenceA_ (Data.Sequence.mapWithIndex k xs)--axiom :: Const -> Either (TypeError s a) Const-axiom Type = return Kind-axiom Kind = return Sort-axiom Sort = Left (TypeError Dhall.Context.empty (Const Sort) Untyped)--rule :: Const -> Const -> Either () Const-rule Type Type = return Type-rule Kind Type = return Type-rule Sort Type = return Type-rule Kind Kind = return Kind-rule Sort Kind = return Sort-rule Sort Sort = return Sort--- This forbids dependent types. If this ever changes, then the fast--- path in the Let case of typeWithA will become unsound.-rule _    _    = Left ()--{-| 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 = loop-  where-    loop _     (Const c         ) = do-        fmap Const (axiom c)-    loop ctx e@(Var (V x n)     ) = do-        case Dhall.Context.lookup x n ctx of-            Nothing -> Left (TypeError ctx e (UnboundVariable x))-            Just a  -> do-                -- Note: no need to typecheck the value we're-                -- returning; that is done at insertion time.-                return a-    loop ctx   (Lam x _A  b     ) = do-        _ <- loop ctx _A-        let ctx' = fmap (Dhall.Core.shift 1 (V x 0)) (Dhall.Context.insert x (Dhall.Core.normalize _A) ctx)-        _B <- loop ctx' b-        let p = Pi x _A _B-        _t <- loop ctx p-        return p-    loop ctx e@(Pi  x _A _B     ) = do-        tA <- fmap Dhall.Core.normalize (loop ctx _A)-        kA <- case tA of-            Const k -> return k-            _       -> Left (TypeError ctx e (InvalidInputType _A))--        let ctx' = fmap (Dhall.Core.shift 1 (V x 0)) (Dhall.Context.insert x (Dhall.Core.normalize _A) ctx)-        tB <- fmap Dhall.Core.normalize (loop ctx' _B)-        kB <- case tB of-            Const k -> return k-            _       -> Left (TypeError ctx' e (InvalidOutputType _B))--        case rule kA kB of-            Left () -> Left (TypeError ctx e (NoDependentTypes _A _B))-            Right k -> Right (Const k)-    loop ctx e@(App f a         ) = do-        tf <- fmap Dhall.Core.normalize (loop ctx f)-        (x, _A, _B) <- case tf of-            Pi x _A _B -> return (x, _A, _B)-            _          -> Left (TypeError ctx e (NotAFunction f tf))-        _A' <- loop ctx a-        if Dhall.Core.judgmentallyEqual _A _A'-            then do-                let a'   = Dhall.Core.shift   1  (V x 0) a-                let _B'  = Dhall.Core.subst (V x 0) a' _B-                let _B'' = Dhall.Core.shift (-1) (V x 0) _B'-                return _B''-            else do-                let nf_A  = Dhall.Core.normalize _A-                let nf_A' = Dhall.Core.normalize _A'-                Left (TypeError ctx e (TypeMismatch f nf_A a nf_A'))-    loop ctx e@(Let (Binding x mA a0 :| ls) b0) = do-        _A1 <- loop ctx a0-        case mA of-            Just _A0 -> do-                _ <- loop ctx _A0-                let nf_A0 = Dhall.Core.normalize _A0-                let nf_A1 = Dhall.Core.normalize _A1-                if Dhall.Core.judgmentallyEqual _A0 _A1-                    then return ()-                    else Left (TypeError ctx e (AnnotMismatch a0 nf_A0 nf_A1))-            Nothing -> return ()--        t <- loop ctx _A1--        let a1 = Dhall.Core.normalize a0-        let a2 = Dhall.Core.shift 1 (V x 0) a1--        let rest = case ls of-                []       -> b0-                l' : ls' -> Let (l' :| ls') b0--        -- The catch-all branch directly implements the Dhall-        -- specification as written; it is necessary to substitute in-        -- types in order to get 'dependent let' behaviour and to-        -- allow type synonyms (see #69). However, doing a full-        -- substitution is slow if the value is large and used many-        -- times. If the value being substitued in is a term (i.e.,-        -- its type is a Type), then we can get a very significant-        -- speed-up by doing the type-checking once at binding-time,-        -- as opposed to doing it at every use site (see #412).-        case Dhall.Core.normalize t of-          Const Type -> do-            let ctx' = fmap (Dhall.Core.shift 1 (V x 0)) (Dhall.Context.insert x (Dhall.Core.normalize _A1) ctx)-            _B0 <- loop ctx' rest-            let _B1 = Dhall.Core.subst (V x 0) a2 _B0-            let _B2 = Dhall.Core.shift (-1) (V x 0) _B1-            return _B2--          _ -> do-            let b1 = Dhall.Core.subst (V x 0) a2 rest-            let b2 = Dhall.Core.shift (-1) (V x 0) b1-            loop ctx b2--    loop ctx e@(Annot x t       ) = do-        _ <- loop ctx t--        t' <- loop ctx x-        if Dhall.Core.judgmentallyEqual t t'-            then do-                return t-            else do-                let nf_t  = Dhall.Core.normalize t-                let nf_t' = Dhall.Core.normalize t'-                Left (TypeError ctx e (AnnotMismatch x nf_t nf_t'))-    loop _      Bool              = do-        return (Const Type)-    loop _     (BoolLit _       ) = do-        return Bool-    loop ctx e@(BoolAnd l r     ) = do-        tl <- fmap Dhall.Core.normalize (loop ctx l)-        case tl of-            Bool -> return ()-            _    -> Left (TypeError ctx e (CantAnd l tl))--        tr <- fmap Dhall.Core.normalize (loop ctx r)-        case tr of-            Bool -> return ()-            _    -> Left (TypeError ctx e (CantAnd r tr))--        return Bool-    loop ctx e@(BoolOr  l r     ) = do-        tl <- fmap Dhall.Core.normalize (loop ctx l)-        case tl of-            Bool -> return ()-            _    -> Left (TypeError ctx e (CantOr l tl))--        tr <- fmap Dhall.Core.normalize (loop ctx r)-        case tr of-            Bool -> return ()-            _    -> Left (TypeError ctx e (CantOr r tr))--        return Bool-    loop ctx e@(BoolEQ  l r     ) = do-        tl <- fmap Dhall.Core.normalize (loop ctx l)-        case tl of-            Bool -> return ()-            _    -> Left (TypeError ctx e (CantEQ l tl))--        tr <- fmap Dhall.Core.normalize (loop ctx r)-        case tr of-            Bool -> return ()-            _    -> Left (TypeError ctx e (CantEQ r tr))--        return Bool-    loop ctx e@(BoolNE  l r     ) = do-        tl <- fmap Dhall.Core.normalize (loop ctx l)-        case tl of-            Bool -> return ()-            _    -> Left (TypeError ctx e (CantNE l tl))--        tr <- fmap Dhall.Core.normalize (loop ctx r)-        case tr of-            Bool -> return ()-            _    -> Left (TypeError ctx e (CantNE r tr))--        return Bool-    loop ctx e@(BoolIf x y z    ) = do-        tx <- fmap Dhall.Core.normalize (loop ctx x)-        case tx of-            Bool -> return ()-            _    -> Left (TypeError ctx e (InvalidPredicate x tx))-        ty  <- fmap Dhall.Core.normalize (loop ctx y )-        tty <- fmap Dhall.Core.normalize (loop ctx ty)-        case tty of-            Const Type -> return ()-            _          -> Left (TypeError ctx e (IfBranchMustBeTerm True y ty tty))--        tz <- fmap Dhall.Core.normalize (loop ctx z)-        ttz <- fmap Dhall.Core.normalize (loop ctx tz)-        case ttz of-            Const Type -> return ()-            _          -> Left (TypeError ctx e (IfBranchMustBeTerm False z tz ttz))--        if Dhall.Core.judgmentallyEqual ty tz-            then return ()-            else Left (TypeError ctx e (IfBranchMismatch y z ty tz))-        return ty-    loop _      Natural           = do-        return (Const Type)-    loop _     (NaturalLit _    ) = do-        return Natural-    loop _      NaturalFold       = do-        return-            (Pi "_" Natural-                (Pi "natural" (Const Type)-                    (Pi "succ" (Pi "_" "natural" "natural")-                        (Pi "zero" "natural" "natural") ) ) )-    loop _      NaturalBuild      = do-        return-            (Pi "_"-                (Pi "natural" (Const Type)-                    (Pi "succ" (Pi "_" "natural" "natural")-                        (Pi "zero" "natural" "natural") ) )-                Natural )-    loop _      NaturalIsZero     = do-        return (Pi "_" Natural Bool)-    loop _      NaturalEven       = do-        return (Pi "_" Natural Bool)-    loop _      NaturalOdd        = do-        return (Pi "_" Natural Bool)-    loop _      NaturalToInteger  = do-        return (Pi "_" Natural Integer)-    loop _      NaturalShow  = do-        return (Pi "_" Natural Text)-    loop ctx e@(NaturalPlus  l r) = do-        tl <- fmap Dhall.Core.normalize (loop ctx l)-        case tl of-            Natural -> return ()-            _       -> Left (TypeError ctx e (CantAdd l tl))--        tr <- fmap Dhall.Core.normalize (loop ctx r)-        case tr of-            Natural -> return ()-            _       -> Left (TypeError ctx e (CantAdd r tr))-        return Natural-    loop ctx e@(NaturalTimes l r) = do-        tl <- fmap Dhall.Core.normalize (loop ctx l)-        case tl of-            Natural -> return ()-            _       -> Left (TypeError ctx e (CantMultiply l tl))--        tr <- fmap Dhall.Core.normalize (loop ctx r)-        case tr of-            Natural -> return ()-            _       -> Left (TypeError ctx e (CantMultiply r tr))-        return Natural-    loop _      Integer           = do-        return (Const Type)-    loop _     (IntegerLit _    ) = do-        return Integer-    loop _      IntegerShow  = do-        return (Pi "_" Integer Text)-    loop _      IntegerToDouble = do-        return (Pi "_" Integer Double)-    loop _      Double            = do-        return (Const Type)-    loop _     (DoubleLit _     ) = do-        return Double-    loop _     DoubleShow         = do-        return (Pi "_" Double Text)-    loop _      Text              = do-        return (Const Type)-    loop ctx e@(TextLit (Chunks xys _)) = do-        let process (_, y) = do-                ty <- fmap Dhall.Core.normalize (loop ctx y)-                case ty of-                    Text -> return ()-                    _    -> Left (TypeError ctx e (CantInterpolate y ty))-        mapM_ process xys-        return Text-    loop ctx e@(TextAppend l r  ) = do-        tl <- fmap Dhall.Core.normalize (loop ctx l)-        case tl of-            Text -> return ()-            _    -> Left (TypeError ctx e (CantTextAppend l tl))--        tr <- fmap Dhall.Core.normalize (loop ctx r)-        case tr of-            Text -> return ()-            _    -> Left (TypeError ctx e (CantTextAppend r tr))-        return Text-    loop _      TextShow          = do-        return (Pi "_" Text Text)-    loop _      List              = do-        return (Pi "_" (Const Type) (Const Type))-    loop ctx e@(ListLit  Nothing  xs) = do-        case Data.Sequence.viewl xs of-            x0 :< _ -> do-                t <- loop ctx x0-                s <- fmap Dhall.Core.normalize (loop ctx t)-                case s of-                    Const Type -> return ()-                    _ -> Left (TypeError ctx e (InvalidListType t))-                flip traverseWithIndex_ xs (\i x -> do-                    t' <- loop ctx x-                    if Dhall.Core.judgmentallyEqual t t'-                        then return ()-                        else do-                            let nf_t  = Dhall.Core.normalize t-                            let nf_t' = Dhall.Core.normalize t'-                            let err   = MismatchedListElements i nf_t x nf_t'-                            Left (TypeError ctx x err) )-                return (App List t)-            _ -> Left (TypeError ctx e MissingListType)-    loop ctx e@(ListLit (Just t ) xs) = do-        s <- fmap Dhall.Core.normalize (loop ctx t)-        case s of-            Const Type -> return ()-            _ -> Left (TypeError ctx e (InvalidListType t))-        flip traverseWithIndex_ xs (\i x -> do-            t' <- loop ctx x-            if Dhall.Core.judgmentallyEqual t t'-                then return ()-                else do-                    let nf_t  = Dhall.Core.normalize t-                    let nf_t' = Dhall.Core.normalize t'-                    Left (TypeError ctx x (InvalidListElement i nf_t x nf_t')) )-        return (App List t)-    loop ctx e@(ListAppend l r  ) = do-        tl <- fmap Dhall.Core.normalize (loop ctx l)-        el <- case tl of-            App List el -> return el-            _           -> Left (TypeError ctx e (CantListAppend l tl))--        tr <- fmap Dhall.Core.normalize (loop ctx r)-        er <- case tr of-            App List er -> return er-            _           -> Left (TypeError ctx e (CantListAppend r tr))--        if Dhall.Core.judgmentallyEqual el er-            then return (App List el)-            else Left (TypeError ctx e (ListAppendMismatch el er))-    loop _      ListBuild         = do-        return-            (Pi "a" (Const Type)-                (Pi "_"-                    (Pi "list" (Const Type)-                        (Pi "cons" (Pi "_" "a" (Pi "_" "list" "list"))-                            (Pi "nil" "list" "list") ) )-                    (App List "a") ) )-    loop _      ListFold          = do-        return-            (Pi "a" (Const Type)-                (Pi "_" (App List "a")-                    (Pi "list" (Const Type)-                        (Pi "cons" (Pi "_" "a" (Pi "_" "list" "list"))-                            (Pi "nil" "list" "list")) ) ) )-    loop _      ListLength        = do-        return (Pi "a" (Const Type) (Pi "_" (App List "a") Natural))-    loop _      ListHead          = do-        return (Pi "a" (Const Type) (Pi "_" (App List "a") (App Optional "a")))-    loop _      ListLast          = do-        return (Pi "a" (Const Type) (Pi "_" (App List "a") (App Optional "a")))-    loop _      ListIndexed       = do-        let kts = [("index", Natural), ("value", "a")]-        return-            (Pi "a" (Const Type)-                (Pi "_" (App List "a")-                    (App List (Record (Dhall.Map.fromList kts))) ) )-    loop _      ListReverse       = do-        return (Pi "a" (Const Type) (Pi "_" (App List "a") (App List "a")))-    loop _      Optional          = do-        return (Pi "_" (Const Type) (Const Type))-    loop _      None              = do-        return (Pi "A" (Const Type) (App Optional "A"))-    loop ctx e@(OptionalLit t xs) = do-        s <- fmap Dhall.Core.normalize (loop ctx t)-        case s of-            Const Type -> return ()-            _ -> Left (TypeError ctx e (InvalidOptionalType t))-        forM_ xs (\x -> do-            t' <- loop ctx x-            if Dhall.Core.judgmentallyEqual t t'-                then return ()-                else do-                    let nf_t  = Dhall.Core.normalize t-                    let nf_t' = Dhall.Core.normalize t'-                    Left (TypeError ctx e (InvalidOptionalElement nf_t x nf_t')) )-        return (App Optional t)-    loop ctx e@(Some a) = do-        _A <- loop ctx a-        s <- fmap Dhall.Core.normalize (loop ctx _A)-        case s of-            Const Type -> return ()-            _          -> Left (TypeError ctx e (InvalidSome a _A s))-        return (App Optional _A)-    loop _      OptionalFold      = do-        return-            (Pi "a" (Const Type)-                (Pi "_" (App Optional "a")-                    (Pi "optional" (Const Type)-                        (Pi "just" (Pi "_" "a" "optional")-                            (Pi "nothing" "optional" "optional") ) ) ) )-    loop _      OptionalBuild     = do-        return-            (Pi "a" (Const Type)-                (Pi "_" f (App Optional "a") ) )-        where f = Pi "optional" (Const Type)-                      (Pi "just" (Pi "_" "a" "optional")-                          (Pi "nothing" "optional" "optional") )-    loop ctx e@(Record    kts   ) = do-        case Dhall.Map.uncons kts of-            Nothing             -> return (Const Type)-            Just (k0, t0, rest) -> do-                s0 <- fmap Dhall.Core.normalize (loop ctx t0)-                c <- case s0 of-                    Const c -> pure c-                    _ -> Left (TypeError ctx e (InvalidFieldType k0 t0))-                let process k t = do-                        s <- fmap Dhall.Core.normalize (loop ctx t)-                        case s of-                            Const c' ->-                                if c == c'-                                then return ()-                                else Left (TypeError ctx e (FieldAnnotationMismatch k t c k0 t0 c'))-                            _ -> Left (TypeError ctx e (InvalidFieldType k t))-                Dhall.Map.unorderedTraverseWithKey_ process rest-                return (Const c)-    loop ctx e@(RecordLit kvs   ) = do-        case Dhall.Map.toList kvs of-            []         -> return (Record mempty)-            (k0, v0):_ -> do-                t0 <- loop ctx v0-                s0 <- fmap Dhall.Core.normalize (loop ctx t0)-                c <- case s0 of-                    Const c -> pure c-                    _       -> Left (TypeError ctx e (InvalidField k0 v0))-                let process k v = do-                        t <- loop ctx v-                        s <- fmap Dhall.Core.normalize (loop ctx t)-                        case s of-                            Const c' ->-                                if c == c'-                                then return ()-                                else Left (TypeError ctx e (FieldMismatch k v c k0 v0 c'))-                            _ -> Left (TypeError ctx e (InvalidField k t))--                        return t-                kts <- Dhall.Map.traverseWithKey process kvs-                return (Record kts)-    loop ctx e@(Union     kts   ) = do-        let nonEmpty k mt = First (fmap (\t -> (k, t)) mt)--        case getFirst (Dhall.Map.foldMapWithKey nonEmpty kts) of-            Nothing -> do-                return (Const Type)--            Just (k0, t0) -> do-                s0 <- fmap Dhall.Core.normalize (loop ctx t0)--                c0 <- case s0 of-                    Const c0 -> do-                        return c0--                    _ -> do-                        Left (TypeError ctx e (InvalidAlternativeType k0 t0))--                let process _ Nothing = do-                        return ()--                    process k (Just t) = do-                        s <- fmap Dhall.Core.normalize (loop ctx t)--                        c <- case s of-                            Const c -> do-                                return c--                            _ -> do-                                Left (TypeError ctx e (InvalidAlternativeType k t))--                        if c0 == c-                            then return ()-                            else Left (TypeError ctx e (AlternativeAnnotationMismatch k t c k0 t0 c0))--                Dhall.Map.unorderedTraverseWithKey_ process kts--                return (Const c0)-    loop ctx e@(UnionLit k v kts) = do-        case Dhall.Map.lookup k kts of-            Just _  -> Left (TypeError ctx e (DuplicateAlternative k))-            Nothing -> return ()-        t <- loop ctx v-        let union = Union (Dhall.Map.insert k (Just (Dhall.Core.normalize t)) kts)-        _ <- loop ctx union-        return union-    loop ctx e@(Combine kvsX kvsY) = do-        tKvsX <- fmap Dhall.Core.normalize (loop ctx kvsX)-        ktsX  <- case tKvsX of-            Record kts -> return kts-            _          -> Left (TypeError ctx e (MustCombineARecord '∧' kvsX tKvsX))--        tKvsY <- fmap Dhall.Core.normalize (loop ctx kvsY)-        ktsY  <- case tKvsY of-            Record kts -> return kts-            _          -> Left (TypeError ctx e (MustCombineARecord '∧' kvsY tKvsY))--        ttKvsX <- fmap Dhall.Core.normalize (loop ctx tKvsX)-        constX <- case ttKvsX of-            Const constX -> return constX-            _            -> Left (TypeError ctx e (MustCombineARecord '∧' kvsX tKvsX))--        ttKvsY <- fmap Dhall.Core.normalize (loop ctx tKvsY)-        constY <- case ttKvsY of-            Const constY -> return constY-            _            -> Left (TypeError ctx e (MustCombineARecord '∧' kvsY tKvsY))--        if constX == constY-            then return ()-            else Left (TypeError ctx e (RecordMismatch '∧' kvsX kvsY constX constY))--        let combineTypes ktsL ktsR = do-                let ksL =-                        Data.Set.fromList (Dhall.Map.keys ktsL)-                let ksR =-                        Data.Set.fromList (Dhall.Map.keys ktsR)-                let ks = Data.Set.union ksL ksR-                kts <- forM (toList ks) (\k -> do-                    case (Dhall.Map.lookup k ktsL, Dhall.Map.lookup k ktsR) of-                        (Just (Record ktsL'), Just (Record ktsR')) -> do-                            t <- combineTypes ktsL' ktsR'-                            return (k, t)-                        (Nothing, Just t) -> do-                            return (k, t)-                        (Just t, Nothing) -> do-                            return (k, t)-                        _ -> do-                            Left (TypeError ctx e (FieldCollision k)) )-                return (Record (Dhall.Map.fromList kts))--        combineTypes ktsX ktsY-    loop ctx e@(CombineTypes l r) = do-        tL <- loop ctx l-        let l' = Dhall.Core.normalize l-        cL <- case tL of-            Const cL -> return cL-            _        -> Left (TypeError ctx e (CombineTypesRequiresRecordType l l'))-        tR <- loop ctx r-        let r' = Dhall.Core.normalize r-        cR <- case tR of-            Const cR -> return cR-            _        -> Left (TypeError ctx e (CombineTypesRequiresRecordType r r'))-        let decide Type Type =-                return Type-            decide Kind Kind =-                return Kind-            decide Sort Sort =-                return Sort-            decide x y =-                Left (TypeError ctx e (RecordTypeMismatch x y l r))-        c <- decide cL cR--        ktsL0 <- case l' of-            Record kts -> return kts-            _          -> Left (TypeError ctx e (CombineTypesRequiresRecordType l l'))-        ktsR0 <- case r' of-            Record kts -> return kts-            _          -> Left (TypeError ctx e (CombineTypesRequiresRecordType r r'))--        let combineTypes ktsL ktsR = do-                let ksL =-                        Data.Set.fromList (Dhall.Map.keys ktsL)-                let ksR =-                        Data.Set.fromList (Dhall.Map.keys ktsR)-                let ks = Data.Set.union ksL ksR-                forM_ (toList ks) (\k -> do-                    case (Dhall.Map.lookup k ktsL, Dhall.Map.lookup k ktsR) of-                        (Just (Record ktsL'), Just (Record ktsR')) -> do-                            combineTypes ktsL' ktsR'-                        (Nothing, Just _) -> do-                            return ()-                        (Just _, Nothing) -> do-                            return ()-                        _ -> do-                            Left (TypeError ctx e (FieldCollision k)) )--        combineTypes ktsL0 ktsR0--        return (Const c)-    loop ctx e@(Prefer kvsX kvsY) = do-        tKvsX <- fmap Dhall.Core.normalize (loop ctx kvsX)-        ktsX  <- case tKvsX of-            Record kts -> return kts-            _          -> Left (TypeError ctx e (MustCombineARecord '⫽' kvsX tKvsX))--        tKvsY <- fmap Dhall.Core.normalize (loop ctx kvsY)-        ktsY  <- case tKvsY of-            Record kts -> return kts-            _          -> Left (TypeError ctx e (MustCombineARecord '⫽' kvsY tKvsY))--        ttKvsX <- fmap Dhall.Core.normalize (loop ctx tKvsX)-        constX <- case ttKvsX of-            Const constX -> return constX-            _            -> Left (TypeError ctx e (MustCombineARecord '⫽' kvsX tKvsX))--        ttKvsY <- fmap Dhall.Core.normalize (loop ctx tKvsY)-        constY <- case ttKvsY of-            Const constY -> return constY-            _            -> Left (TypeError ctx e (MustCombineARecord '⫽' kvsY tKvsY))--        if constX == constY-            then return ()-            else Left (TypeError ctx e (RecordMismatch '⫽' kvsX kvsY constX constY))--        return (Record (Dhall.Map.union ktsY ktsX))-    loop ctx e@(Merge kvsX kvsY mT₁) = do-        tKvsX <- fmap Dhall.Core.normalize (loop ctx kvsX)--        ktsX <- case tKvsX of-            Record kts -> return kts-            _          -> Left (TypeError ctx e (MustMergeARecord kvsX tKvsX))--        tKvsY <- fmap Dhall.Core.normalize (loop ctx kvsY)--        ktsY <- case tKvsY of-            Union kts -> return kts-            _         -> Left (TypeError ctx e (MustMergeUnion kvsY tKvsY))--        let ksX = Data.Set.fromList (Dhall.Map.keys ktsX)-        let ksY = Data.Set.fromList (Dhall.Map.keys ktsY)--        let diffX = Data.Set.difference ksX ksY-        let diffY = Data.Set.difference ksY ksX--        if Data.Set.null diffX-            then return ()-            else Left (TypeError ctx e (UnusedHandler diffX))--        (mKX, _T₁) <- do-            case mT₁ of-                Just _T₁ -> do-                    return (Nothing, _T₁)--                Nothing -> do-                    case Dhall.Map.uncons ktsX of-                        Nothing -> do-                            Left (TypeError ctx e MissingMergeType)--                        Just (kX, tX, _) -> do-                            _T₁ <- do-                                case Dhall.Map.lookup kX ktsY of-                                    Nothing -> do-                                        Left (TypeError ctx e (UnusedHandler diffX))--                                    Just Nothing -> do-                                        return tX--                                    Just (Just _)  ->-                                        case tX of-                                            Pi x _A₀ _T₀ -> do-                                                return (Dhall.Core.shift (-1) (V x 0) _T₀)-                                            _ -> do-                                                Left (TypeError ctx e (HandlerNotAFunction kX tX))--                            return (Just kX, _T₁)--        _ <- loop ctx _T₁--        let process kY mTY = do-                case Dhall.Map.lookup kY ktsX of-                    Nothing -> do-                        Left (TypeError ctx e (MissingHandler diffY))--                    Just tX -> do-                        _T₃ <- do-                            case mTY of-                                Nothing -> do-                                    return tX-                                Just _A₁ -> do-                                    case tX of-                                        Pi x _A₀ _T₂ -> do-                                            if Dhall.Core.judgmentallyEqual _A₀ _A₁-                                                then return ()-                                                else Left (TypeError ctx e (HandlerInputTypeMismatch kY _A₁ _A₀))--                                            return (Dhall.Core.shift (-1) (V x 0) _T₂)-                                        _ -> do-                                            Left (TypeError ctx e (HandlerNotAFunction kY tX))--                        if Dhall.Core.judgmentallyEqual _T₁ _T₃-                            then return ()-                            else-                                case mKX of-                                    Nothing -> do-                                        Left (TypeError ctx e (InvalidHandlerOutputType kY _T₁ _T₃))-                                    Just kX -> do-                                        Left (TypeError ctx e (HandlerOutputTypeMismatch kX _T₁ kY _T₃))--        Dhall.Map.unorderedTraverseWithKey_ process ktsY--        return _T₁-    loop ctx e@(Field r x       ) = do-        t <- fmap Dhall.Core.normalize (loop ctx r)--        let text = Dhall.Pretty.Internal.docToStrictText (Dhall.Pretty.Internal.prettyLabel x)--        case t of-            Record kts -> do-                _ <- loop ctx t--                case Dhall.Map.lookup x kts of-                    Just t' -> return t'-                    Nothing -> Left (TypeError ctx e (MissingField x t))-            _ -> do-                case Dhall.Core.normalize r of-                  Union kts ->-                    case Dhall.Map.lookup x kts of-                        Just (Just t') -> return (Pi x t' (Union kts))-                        Just Nothing   -> return (Union kts)-                        Nothing -> Left (TypeError ctx e (MissingField x t))-                  r' -> Left (TypeError ctx e (CantAccess text r' t))-    loop ctx e@(Project r (Left xs)) = do-        t <- fmap Dhall.Core.normalize (loop ctx r)--        case t of-            Record kts -> do-                _ <- loop ctx t--                let process k =-                        case Dhall.Map.lookup k kts of-                            Just t' -> return (k, t')-                            Nothing -> Left (TypeError ctx e (MissingField k t))--                let adapt = Record . Dhall.Map.fromList--                fmap adapt (traverse process (Dhall.Set.toList xs))-            _ -> do-                let text =-                        Dhall.Pretty.Internal.docToStrictText (Dhall.Pretty.Internal.prettyLabels xs)--                Left (TypeError ctx e (CantProject text r t))-    loop ctx e@(Project r (Right t)) = do-        _R <- loop ctx r--        case _R of-            Record ktsR -> do-                _ <- fmap Dhall.Core.normalize (loop ctx t)--                case Dhall.Core.normalize t of-                    Record ktsT -> do-                        let keysR = Dhall.Set.fromList (Dhall.Map.keys ktsR)-                        let keysT = Dhall.Set.fromList (Dhall.Map.keys ktsT)--                        case Dhall.Set.difference keysT keysR of-                            k : _ -> do-                                Left (TypeError ctx e (MissingField k t))-                            [] -> do-                                return (Record ktsT)-                    _ -> do-                        Left (TypeError ctx e (CantProjectByExpression t))--            _ -> do-                let text = Dhall.Core.pretty t--                Left (TypeError ctx e (CantProject text r t))-    loop ctx   (Note s e'       ) = case loop ctx e' of-        Left (TypeError ctx' (Note s' e'') m) -> Left (TypeError ctx' (Note s' e'') m)-        Left (TypeError ctx'          e''  m) -> Left (TypeError ctx' (Note s  e'') m)-        Right r                               -> Right r-    loop ctx   (ImportAlt l _r  ) =-       fmap Dhall.Core.normalize (loop ctx l)-    loop _     (Embed p         ) = Right $ tpa p--{-| `typeOf` is the same as `typeWith` with an empty context, meaning that the-    expression must be closed (i.e. no free variables), otherwise type-checking-    will fail.--}-typeOf :: Expr s X -> Either (TypeError s X) (Expr s X)-typeOf = typeWith Dhall.Context.empty---- | Like `Data.Void.Void`, except with a shorter inferred type-newtype X = X { absurd :: forall a . a }--instance Show X where-    show = absurd--instance Eq X where-  _ == _ = True--instance Data X where-    dataTypeOf = absurd-    gunfold _ _ _ = undefined-    toConstr = absurd--instance Pretty X where-    pretty = absurd--instance FromTerm X where-    decode _ = empty--instance ToTerm X where-    encode = absurd---- | The specific type error-data TypeMessage s a-    = UnboundVariable Text-    | InvalidInputType (Expr s a)-    | InvalidOutputType (Expr s a)-    | NotAFunction (Expr s a) (Expr s a)-    | TypeMismatch (Expr s a) (Expr s a) (Expr s a) (Expr s a)-    | AnnotMismatch (Expr s a) (Expr s a) (Expr s a)-    | Untyped-    | MissingListType-    | MismatchedListElements Int (Expr s a) (Expr s a) (Expr s a)-    | InvalidListElement Int (Expr s a) (Expr s a) (Expr s a)-    | InvalidListType (Expr s a)-    | InvalidOptionalElement (Expr s a) (Expr s a) (Expr s a)-    | InvalidOptionalType (Expr s a)-    | 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)-    | InvalidField Text (Expr s a)-    | InvalidFieldType Text (Expr s a)-    | FieldAnnotationMismatch Text (Expr s a) Const Text (Expr s a) Const-    | FieldMismatch Text (Expr s a) Const Text (Expr s a) Const-    | InvalidAlternative Text (Expr s a)-    | InvalidAlternativeType Text (Expr s a)-    | AlternativeAnnotationMismatch Text (Expr s a) Const Text (Expr s a) Const-    | ListAppendMismatch (Expr s a) (Expr s a)-    | DuplicateAlternative Text-    | MustCombineARecord Char (Expr s a) (Expr s a)-    | RecordMismatch Char (Expr s a) (Expr s a) Const Const-    | CombineTypesRequiresRecordType (Expr s a) (Expr s a)-    | RecordTypeMismatch Const Const (Expr s a) (Expr s a)-    | FieldCollision Text-    | MustMergeARecord (Expr s a) (Expr s a)-    | MustMergeUnion (Expr s a) (Expr s a)-    | UnusedHandler (Set Text)-    | MissingHandler (Set Text)-    | HandlerInputTypeMismatch Text (Expr s a) (Expr s a)-    | HandlerOutputTypeMismatch Text (Expr s a) Text (Expr s a)-    | InvalidHandlerOutputType Text (Expr s a) (Expr s a)-    | MissingMergeType-    | HandlerNotAFunction Text (Expr s a)-    | ConstructorsRequiresAUnionType (Expr s a) (Expr s a)-    | 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)-    | CantAnd (Expr s a) (Expr s a)-    | CantOr (Expr s a) (Expr s a)-    | CantEQ (Expr s a) (Expr s a)-    | CantNE (Expr s a) (Expr s a)-    | CantInterpolate (Expr s a) (Expr s a)-    | CantTextAppend (Expr s a) (Expr s a)-    | CantListAppend (Expr s a) (Expr s a)-    | CantAdd (Expr s a) (Expr s a)-    | CantMultiply (Expr s a) (Expr s a)-    | NoDependentTypes (Expr s a) (Expr s a)-    deriving (Show)--shortTypeMessage :: (Eq a, Pretty a, ToTerm a) => TypeMessage s a -> Doc Ann-shortTypeMessage msg =-    "\ESC[1;31mError\ESC[0m: " <> short <> "\n"-  where-    ErrorMessages {..} = prettyTypeMessage msg--longTypeMessage :: (Eq a, Pretty a, ToTerm a) => TypeMessage s a -> Doc Ann-longTypeMessage msg =-        "\ESC[1;31mError\ESC[0m: " <> short <> "\n"-    <>  "\n"-    <>  long-  where-    ErrorMessages {..} = prettyTypeMessage msg--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--prettyDiff :: (Eq a, Pretty a, ToTerm a) => Expr s a -> Expr s a -> Doc Ann-prettyDiff exprL exprR = Dhall.Diff.diffNormalized exprL exprR--prettyTypeMessage-    :: (Eq a, Pretty a, ToTerm 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"-        <>  prettyDiff 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"-        <>  prettyDiff 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❱"--    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"-        <>  prettyDiff 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 (InvalidListType expr0) = ErrorMessages {..}-  where-    short = "Invalid type for ❰List❱ elements"--    long =-        "Explanation: ❰List❱s can optionally document the type of their elements with a  \n\-        \type annotation, like this:                                                     \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────────────────────┐                                                \n\-        \    │ [1, 2, 3] : List 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 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❱'s elements should have type:                       \n\-        \                                                                                \n\-        \" <> txt0 <> "\n\-        \                                                                                \n\-        \... which is not a ❰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"-        <>  prettyDiff 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"-        <>  prettyDiff 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 (InvalidOptionalType expr0) = ErrorMessages {..}-  where-    short = "Invalid type for ❰Optional❱ element"--    long =-        "Explanation: The legacy ❰List❱-like syntax for ❰Optional❱ literals ends with a  \n\-        \type annotation for the element that might be present, like this:               \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────────┐                                                  \n\-        \    │ [1] : Optional Natural │  An optional element that's present              \n\-        \    └────────────────────────┘                                                  \n\-        \                     ⇧                                                          \n\-        \                     The type of the ❰Optional❱ element, which is an ❰Natural❱  \n\-        \                     number                                                     \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────────┐                                                  \n\-        \    │ [] : Optional Natural  │  An optional element that's absent               \n\-        \    └────────────────────────┘                                                  \n\-        \                    ⇧                                                           \n\-        \                    You still specify the type even when the element is absent  \n\-        \                                                                                \n\-        \                                                                                \n\-        \The element type must be a type and not something else.  For example, the       \n\-        \following element types are " <> _NOT <> " valid:                               \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────────────┐                                                        \n\-        \    │ ... : Optional 1 │                                                        \n\-        \    └──────────────────┘                                                        \n\-        \                     ⇧                                                          \n\-        \                     This is a ❰Natural❱ number and not a ❰Type❱                \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────┐                                                     \n\-        \    │ ... : Optional Type │                                                     \n\-        \    └─────────────────────┘                                                     \n\-        \                     ⇧                                                          \n\-        \                     This is a ❰Kind❱ and not a ❰Type❱                          \n\-        \                                                                                \n\-        \                                                                                \n\-        \Even if the element is absent you still must specify a valid type               \n\-        \                                                                                \n\-        \You declared that the ❰Optional❱ element should have type:                      \n\-        \                                                                                \n\-        \" <> txt0 <> "\n\-        \                                                                                \n\-        \... which is not a ❰Type❱                                                       \n"-      where-        txt0 = insert expr0--prettyTypeMessage (InvalidOptionalElement expr0 expr1 expr2) = ErrorMessages {..}-  where-    short = "❰Optional❱ element has the wrong type\n"-        <>  "\n"-        <>  prettyDiff expr0 expr2--    long =-        "Explanation: An ❰Optional❱ element must have a type matching the type annotation\n\-        \                                                                                \n\-        \For example, this is a valid ❰Optional❱ value:                                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────────┐                                                  \n\-        \    │ [1] : Optional Natural │  ❰1❱ is a ❰Natural❱ number, which matches the    \n\-        \    └────────────────────────┘  number                                          \n\-        \                                                                                \n\-        \                                                                                \n\-        \... but this is " <> _NOT <> " a valid ❰Optional❱ value:                        \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────────────┐                                              \n\-        \    │ [\"ABC\"] : Optional Natural │  ❰\"ABC\"❱ is not a ❰Natural❱ number       \n\-        \    └────────────────────────────┘                                              \n\-        \                                                                                \n\-        \                                                                                \n\-        \Your ❰Optional❱ element should have this type:                                  \n\-        \                                                                                \n\-        \" <> txt0 <> "\n\-        \                                                                                \n\-        \... but the element you provided:                                               \n\-        \                                                                                \n\-        \" <> txt1 <> "\n\-        \                                                                                \n\-        \... has this type instead:                                                      \n\-        \                                                                                \n\-        \" <> txt2 <> "\n"-      where-        txt0 = insert expr0-        txt1 = insert expr1-        txt2 = 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 (FieldAnnotationMismatch k0 expr0 c0 k1 expr1 c1) = ErrorMessages {..}-  where-    short = "Field annotation mismatch"--    long =-        "Explanation: Every record type annotates each field with a ❰Type❱ or a ❰Kind❱,  \n\-        \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, you cannot have a record type with both a ❰Type❱ and ❰Kind❱ annotation:\n\-        \                                                                                \n\-        \                                                                                \n\-        \              This is a ❰Type❱ annotation                                       \n\-        \              ⇩                                                                 \n\-        \    ┌───────────────────────────────┐                                           \n\-        \    │ { foo : Natural, bar : Type } │  Invalid record type                      \n\-        \    └───────────────────────────────┘                                           \n\-        \                             ⇧                                                  \n\-        \                             ... but this is a ❰Kind❱ annotation                \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 a " <> level c1 <> " whereas another field named:                  \n\-        \                                                                                \n\-        \" <> txt2 <> "\n\-        \                                                                                \n\-        \... annotated with the following expression:                                    \n\-        \                                                                                \n\-        \" <> txt3 <> "\n\-        \                                                                                \n\-        \... is a " <> level c0 <> ", which does not match                               \n"-      where-        txt0 = insert k0-        txt1 = insert expr0-        txt2 = insert k1-        txt3 = insert expr1--        level Type = "❰Type❱"-        level Kind = "❰Kind❱"-        level Sort = "❰Sort❱"--prettyTypeMessage (FieldMismatch k0 expr0 c0 k1 expr1 c1) = ErrorMessages {..}-  where-    short = "Field mismatch"--    long =-        "Explanation: Every record has fields that can be either terms or types, like    \n\-        \this:                                                                           \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────────────────────────────────┐                                    \n\-        \    │ { foo = 1, bar = True, baz = \"ABC\" } │  Every field is a term           \n\-        \    └──────────────────────────────────────┘                                    \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────────┐                                           \n\-        \    │ { foo = Natural, bar = Text } │  Every field is a type                    \n\-        \    └───────────────────────────────┘                                           \n\-        \                                                                                \n\-        \                                                                                \n\-        \However, you cannot have a record that stores both terms and types:             \n\-        \                                                                                \n\-        \                                                                                \n\-        \              This is a term                                                    \n\-        \              ⇩                                                                 \n\-        \    ┌─────────────────────────┐                                                 \n\-        \    │ { foo = 1, bar = Bool } │  Invalid record                                 \n\-        \    └─────────────────────────┘                                                 \n\-        \                       ⇧                                                        \n\-        \                       ... but this is a type                                   \n\-        \                                                                                \n\-        \                                                                                \n\-        \You provided a record with a field named:                                       \n\-        \                                                                                \n\-        \" <> txt0 <> "\n\-        \                                                                                \n\-        \... whose value was:                                                            \n\-        \                                                                                \n\-        \" <> txt1 <> "\n\-        \                                                                                \n\-        \... which is a " <> level c1 <> " whereas another field named:                  \n\-        \                                                                                \n\-        \" <> txt2 <> "\n\-        \                                                                                \n\-        \... whose value was:                                                            \n\-        \                                                                                \n\-        \" <> txt3 <> "\n\-        \                                                                                \n\-        \... is a " <> level c0 <> ", which does not match                               \n"-      where-        txt0 = insert k0-        txt1 = insert expr0-        txt2 = insert k1-        txt3 = insert expr1--        level Type = "term"-        level Kind = "type"-        level Sort = "kind"--prettyTypeMessage (InvalidField k expr0) = ErrorMessages {..}-  where-    short = "Invalid field"--    long =-        "Explanation: Every record literal is a set of fields assigned to values, like   \n\-        \this:                                                                           \n\-        \                                                                                \n\-        \    ┌────────────────────────────────────────┐                                  \n\-        \    │ { foo = 100, bar = True, baz = \"ABC\" } │                                \n\-        \    └────────────────────────────────────────┘                                  \n\-        \                                                                                \n\-        \However, fields can only be terms and or ❰Type❱s and not ❰Kind❱s                \n\-        \                                                                                \n\-        \For example, the following record literal is " <> _NOT <> " valid:              \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────┐                                                          \n\-        \    │ { foo = Type } │                                                          \n\-        \    └────────────────┘                                                          \n\-        \              ⇧                                                                 \n\-        \              ❰Type❱ is a ❰Kind❱, which is not allowed                          \n\-        \                                                                                \n\-        \                                                                                \n\-        \You provided a record literal with a field named:                               \n\-        \                                                                                \n\-        \" <> txt0 <> "\n\-        \                                                                                \n\-        \... whose value is:                                                             \n\-        \                                                                                \n\-        \" <> txt1 <> "\n\-        \                                                                                \n\-        \... which is not a term or ❰Type❱                                               \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 (InvalidAlternative k expr0) = ErrorMessages {..}-  where-    short = "Invalid alternative"--    long =-        "Explanation: Every union literal begins by selecting one alternative and        \n\-        \specifying the value for that alternative, like this:                           \n\-        \                                                                                \n\-        \                                                                                \n\-        \        Select the ❰Left❱ alternative, whose value is ❰True❱                    \n\-        \        ⇩                                                                       \n\-        \    ┌──────────────────────────────────┐                                        \n\-        \    │ < Left = True, Right : Natural > │  A union literal with two alternatives \n\-        \    └──────────────────────────────────┘                                        \n\-        \                                                                                \n\-        \                                                                                \n\-        \However, this value must be a term, type, or kind.  For example, the following  \n\-        \values are " <> _NOT <> " valid:                                                \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────┐                                                         \n\-        \    │ < Left = Sort > │  Invalid union literal                                  \n\-        \    └─────────────────┘                                                         \n\-        \               ⇧                                                                \n\-        \               This is not a term, type, or kind                                \n\-        \                                                                                \n\-        \                                                                                \n\-        \────────────────────────────────────────────────────────────────────────────────\n\-        \                                                                                \n\-        \You provided a union literal with an alternative named:                         \n\-        \                                                                                \n\-        \" <> txt0 <> "\n\-        \                                                                                \n\-        \... whose value is:                                                             \n\-        \                                                                                \n\-        \" <> txt1 <> "\n\-        \                                                                                \n\-        \... which is not a term, type, or kind.                                         \n"-      where-        txt0 = insert k-        txt1 = insert expr0--prettyTypeMessage (AlternativeAnnotationMismatch k0 expr0 c0 k1 expr1 c1) = ErrorMessages {..}-  where-    short = "Alternative annotation mismatch"--    long =-        "Explanation: Every union type annotates each alternative with a ❰Type❱ or a     \n\-        \❰Kind❱, like this:                                                              \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────────────┐                                       \n\-        \    │ < Left : Natural | Right : Bool > │  Every alternative is annotated with a\n\-        \    └───────────────────────────────────┘  ❰Type❱                               \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────────────────────┐                                      \n\-        \    │ < Foo : Type → Type | Bar : Type > │  Every alternative is annotated with \n\-        \    └────────────────────────────────────┘  a ❰Kind❱                            \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────┐                                                          \n\-        \    │ < Baz : Kind > │  Every alternative is annotated with a ❰Sort❱            \n\-        \    └────────────────┘                                                          \n\-        \                                                                                \n\-        \                                                                                \n\-        \However, you cannot have a union type that mixes ❰Type❱s, ❰Kind❱s, or ❰Sort❱s   \n\-        \for the annotations:                                                            \n\-        \                                                                                \n\-        \                                                                                \n\-        \              This is a ❰Type❱ annotation                                       \n\-        \              ⇩                                                                 \n\-        \    ┌───────────────────────────────┐                                           \n\-        \    │ { foo : Natural, bar : Type } │  Invalid union type                       \n\-        \    └───────────────────────────────┘                                           \n\-        \                             ⇧                                                  \n\-        \                             ... but this is a ❰Kind❱ annotation                \n\-        \                                                                                \n\-        \                                                                                \n\-        \You provided a union type with an alternative named:                            \n\-        \                                                                                \n\-        \" <> txt0 <> "\n\-        \                                                                                \n\-        \... annotated with the following expression:                                    \n\-        \                                                                                \n\-        \" <> txt1 <> "\n\-        \                                                                                \n\-        \... which is a " <> level c0 <> " whereas another alternative named:            \n\-        \                                                                                \n\-        \" <> txt2 <> "\n\-        \                                                                                \n\-        \... annotated with the following expression:                                    \n\-        \                                                                                \n\-        \" <> txt3 <> "\n\-        \                                                                                \n\-        \... is a " <> level c1 <> ", which does not match                               \n"-      where-        txt0 = insert k0-        txt1 = insert expr0-        txt2 = insert k1-        txt3 = insert expr1--        level Type = "❰Type❱"-        level Kind = "❰Kind❱"-        level Sort = "❰Sort❱"--prettyTypeMessage (ListAppendMismatch expr0 expr1) = ErrorMessages {..}-  where-    short = "You can only append ❰List❱s with matching element types\n"-        <>  "\n"-        <>  prettyDiff 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 (DuplicateAlternative k) = ErrorMessages {..}-  where-    short = "Duplicate union alternative"--    long =-        "Explanation: Unions may not have two alternatives that share the same name      \n\-        \                                                                                \n\-        \For example, the following expressions are " <> _NOT <> " valid:                \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────┐                                             \n\-        \    │ < foo = True | foo : Text > │  Invalid: ❰foo❱ appears twice               \n\-        \    └─────────────────────────────┘                                             \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────────────────┐                                   \n\-        \    │ < foo = 1 | bar : Bool | bar : Text > │  Invalid: ❰bar❱ appears twice     \n\-        \    └───────────────────────────────────────┘                                   \n\-        \                                                                                \n\-        \                                                                                \n\-        \You have more than one alternative named:                                       \n\-        \                                                                                \n\-        \" <> txt0 <> "\n"-      where-        txt0 = insert k--prettyTypeMessage (MustCombineARecord c expr0 expr1) = ErrorMessages {..}-  where-    short = "You can only combine records"--    long =-        "Explanation: You can combine records using the ❰" <> op <> "❱ operator, like this:\n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────────────────────┐                               \n\-        \    │ { foo = 1, bar = \"ABC\" } " <> op <> " { baz = True } │                  \n\-        \    └───────────────────────────────────────────┘                               \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────────────────┐                             \n\-        \    │ λ(r : { foo : Bool }) → r " <> op <> " { bar = \"ABC\" } │                \n\-        \    └─────────────────────────────────────────────┘                             \n\-        \                                                                                \n\-        \                                                                                \n\-        \... but you cannot combine values that are not records.                         \n\-        \                                                                                \n\-        \For example, the following expressions are " <> _NOT <> " valid:                \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────────────────────────┐                                            \n\-        \    │ { foo = 1, bar = \"ABC\" } " <> op <> " 1 │                               \n\-        \    └──────────────────────────────┘                                            \n\-        \                                 ⇧                                              \n\-        \                                 Invalid: Not a record                          \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────────────────────┐                               \n\-        \    │ { foo = 1, bar = \"ABC\" } " <> op <> " { baz : Bool } │                  \n\-        \    └───────────────────────────────────────────┘                               \n\-        \                                 ⇧                                              \n\-        \                                 Invalid: This is a record type and not a record\n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────────────────────┐                               \n\-        \    │ { foo = 1, bar = \"ABC\" } " <> op <> " < baz = True > │                  \n\-        \    └───────────────────────────────────────────┘                               \n\-        \                                 ⇧                                              \n\-        \                                 Invalid: This is a union and not a record      \n\-        \                                                                                \n\-        \                                                                                \n\-        \You tried to combine the following value:                                       \n\-        \                                                                                \n\-        \" <> txt0 <> "\n\-        \                                                                                \n\-        \... which is not a record, but is actually a:                                   \n\-        \                                                                                \n\-        \" <> txt1 <> "\n"-      where-        op   = pretty c-        txt0 = insert expr0-        txt1 = insert expr1--prettyTypeMessage (RecordMismatch c expr0 expr1 const0 const1) = ErrorMessages {..}-  where-    short = "Record mismatch"--    long =-        "Explanation: You can only use the ❰" <> op <> "❱ operator to combine records if they both  \n\-        \store terms or both store types.                                                \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────────────────────────┐                                            \n\-        \    │ { foo = 1 } " <> op <> " { baz = True } │  Valid: Both records store terms           \n\-        \    └──────────────────────────────┘                                            \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────┐                                         \n\-        \    │ { foo = Bool } " <> op <> " { bar = Text } │  Valid: Both records store types        \n\-        \    └─────────────────────────────────┘                                         \n\-        \                                                                                \n\-        \                                                                                \n\-        \... but you cannot combine two records if one of the records stores types and   \n\-        \the other record stores terms.                                                  \n\-        \                                                                                \n\-        \For example, the following expression is " <> _NOT <> " valid:                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \      Record of terms                                                           \n\-        \      ⇩                                                                         \n\-        \    ┌──────────────────────────────┐                                            \n\-        \    │ { foo = 1 } " <> op <> " { bar = Text } │  Invalid: Mixing terms and types           \n\-        \    └──────────────────────────────┘                                            \n\-        \                               ⇧                                                \n\-        \                               Record of types                                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \You tried to combine the following record:                                      \n\-        \                                                                                \n\-        \" <> txt0 <> "\n\-        \                                                                                \n\-        \... which stores " <> class0 <> ", with the following record:                   \n\-        \                                                                                \n\-        \" <> txt1 <> "\n\-        \                                                                                \n\-        \... which stores " <> class1 <> ".                                              \n"-      where-        op   = pretty c--        txt0 = insert expr0-        txt1 = insert expr1--        toClass Type = "terms"-        toClass Kind = "types"-        toClass Sort = "kinds"--        class0 = toClass const0-        class1 = toClass const1--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 (FieldCollision k) = ErrorMessages {..}-  where-    short = "Field collision"--    long =-        "Explanation: You can combine records or record types if they don't share any    \n\-        \fields in common, like this:                                                    \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────────────────────┐                               \n\-        \    │ { foo = 1, bar = \"ABC\" } ∧ { baz = True } │                             \n\-        \    └───────────────────────────────────────────┘                               \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────┐                                         \n\-        \    │ { foo : Text } ⩓ { bar : Bool } │                                         \n\-        \    └─────────────────────────────────┘                                         \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────────────────────────┐                                  \n\-        \    │ λ(r : { baz : Bool}) → { foo = 1 } ∧ r │                                  \n\-        \    └────────────────────────────────────────┘                                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \... but you cannot merge two records that share the same field unless the field \n\-        \is a record on both sides.                                                      \n\-        \                                                                                \n\-        \For example, the following expressions are " <> _NOT <> " valid:                \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────────────────────┐                               \n\-        \    │ { foo = 1, bar = \"ABC\" } ∧ { foo = True } │  Invalid: Colliding ❰foo❱   \n\-        \    └───────────────────────────────────────────┘  fields                       \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────┐                                         \n\-        \    │ { foo : Bool } ∧ { foo : Text } │  Invalid: Colliding ❰foo❱ fields        \n\-        \    └─────────────────────────────────┘                                         \n\-        \                                                                                \n\-        \                                                                                \n\-        \... but the following expressions are valid:                                    \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────────────────────────────────────────────┐                        \n\-        \    │ { foo = { bar = True } } ∧ { foo = { baz = 1 } } │  Valid: Both ❰foo❱     \n\-        \    └──────────────────────────────────────────────────┘  fields are records    \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────────────────────────┐                     \n\-        \    │ { foo : { bar : Bool } } ⩓ { foo : { baz : Text } } │  Valid: Both ❰foo❱  \n\-        \    └─────────────────────────────────────────────────────┘  fields are records \n\-        \                                                                                \n\-        \                                                                                \n\-        \Some common reasons why you might get this error:                               \n\-        \                                                                                \n\-        \● You tried to use ❰∧❱ to update a field's value, like this:                    \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────────────────────────┐                                  \n\-        \    │ { foo = 1, bar = \"ABC\" } ∧ { foo = 2 } │                                \n\-        \    └────────────────────────────────────────┘                                  \n\-        \                                   ⇧                                            \n\-        \                                  Invalid attempt to update ❰foo❱'s value to ❰2❱\n\-        \                                                                                \n\-        \  Field updates are intentionally not allowed as the Dhall language discourages \n\-        \  patch-oriented programming                                                    \n\-        \                                                                                \n\-        \────────────────────────────────────────────────────────────────────────────────\n\-        \                                                                                \n\-        \You combined two records that share the following field:                        \n\-        \                                                                                \n\-        \" <> txt0 <> "\n\-        \                                                                                \n\-        \... which is not allowed                                                        \n"-      where-        txt0 = insert k--prettyTypeMessage (MustMergeARecord expr0 expr1) = ErrorMessages {..}-  where-    short = "❰merge❱ expects a record of handlers"--    long =-        "Explanation: You can ❰merge❱ the alternatives of a union using a record with one\n\-        \handler per alternative, like this:                                             \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────────────────────────────────────────┐     \n\-        \    │     let union    = < Left = 2 | Right : Bool >                      │     \n\-        \    │ in  let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │     \n\-        \    │ in  merge handlers union : Bool                                     │     \n\-        \    └─────────────────────────────────────────────────────────────────────┘     \n\-        \                                                                                \n\-        \                                                                                \n\-        \... but the first argument to ❰merge❱ must be a record and not some other type. \n\-        \                                                                                \n\-        \For example, the following expression is " <> _NOT <> " valid:                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────────────┐                                 \n\-        \    │ let handler = λ(x : Bool) → x           │                                 \n\-        \    │ in  merge handler < Foo = True > : True │                                 \n\-        \    └─────────────────────────────────────────┘                                 \n\-        \                ⇧                                                               \n\-        \                Invalid: ❰handler❱ isn't a record                               \n\-        \                                                                                \n\-        \                                                                                \n\-        \Some common reasons why you might get this error:                               \n\-        \                                                                                \n\-        \● You accidentally provide an empty record type instead of an empty record when \n\-        \  you ❰merge❱ an empty union:                                                   \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────────────────────────────────────┐                                \n\-        \    │ λ(x : <>) → λ(a : Type) → merge {} x : a │                                \n\-        \    └──────────────────────────────────────────┘                                \n\-        \                                      ⇧                                         \n\-        \                                      This should be ❰{=}❱ instead              \n\-        \                                                                                \n\-        \                                                                                \n\-        \────────────────────────────────────────────────────────────────────────────────\n\-        \                                                                                \n\-        \You provided the following handler:                                             \n\-        \                                                                                \n\-        \" <> txt0 <> "\n\-        \                                                                                \n\-        \... which is not a record, but is actually a value of type:                     \n\-        \                                                                                \n\-        \" <> txt1 <> "\n"-      where-        txt0 = insert expr0-        txt1 = insert expr1--prettyTypeMessage (MustMergeUnion expr0 expr1) = ErrorMessages {..}-  where-    short = "❰merge❱ expects a union"--    long =-        "Explanation: You can ❰merge❱ the alternatives of a union using a record with one\n\-        \handler per alternative, like this:                                             \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────────────────────────────────────────┐     \n\-        \    │     let union    = < Left = 2 | Right : Bool >                      │     \n\-        \    │ in  let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │     \n\-        \    │ in  merge handlers union : Bool                                     │     \n\-        \    └─────────────────────────────────────────────────────────────────────┘     \n\-        \                                                                                \n\-        \                                                                                \n\-        \... but the second argument to ❰merge❱ must be a union and not some other type. \n\-        \                                                                                \n\-        \For example, the following expression is " <> _NOT <> " valid:                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────────────────────────────────────┐                                \n\-        \    │ let handlers = { Foo = λ(x : Bool) → x } │                                \n\-        \    │ in  merge handlers True : True           │                                \n\-        \    └──────────────────────────────────────────┘                                \n\-        \                         ⇧                                                      \n\-        \                         Invalid: ❰True❱ isn't a union                          \n\-        \                                                                                \n\-        \                                                                                \n\-        \You tried to ❰merge❱ this expression:                                           \n\-        \                                                                                \n\-        \" <> txt0 <> "\n\-        \                                                                                \n\-        \... which is not a union, but is actually a value of type:                      \n\-        \                                                                                \n\-        \" <> txt1 <> "\n"-      where-        txt0 = insert expr0-        txt1 = insert expr1--prettyTypeMessage (UnusedHandler ks) = ErrorMessages {..}-  where-    short = "Unused handler"--    long =-        "Explanation: You can ❰merge❱ the alternatives of a union using a record with one\n\-        \handler per alternative, like this:                                             \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────────────────────────────────────────┐     \n\-        \    │     let union    = < Left = 2 | Right : Bool >                      │     \n\-        \    │ in  let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │     \n\-        \    │ in  merge handlers union : Bool                                     │     \n\-        \    └─────────────────────────────────────────────────────────────────────┘     \n\-        \                                                                                \n\-        \                                                                                \n\-        \... but you must provide exactly one handler per alternative in the union.  You \n\-        \cannot supply extra handlers                                                    \n\-        \                                                                                \n\-        \For example, the following expression is " <> _NOT <> " valid:                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────────────────┐                                   \n\-        \    │     let union    = < Left = 2 >       │  The ❰Right❱ alternative is       \n\-        \    │ in  let handlers =                    │  missing                          \n\-        \    │             { Left  = Natural/even    │                                   \n\-        \    │             , Right = λ(x : Bool) → x │  Invalid: ❰Right❱ handler isn't   \n\-        \    │             }                         │           used                    \n\-        \    │ in  merge handlers union : Bool       │                                   \n\-        \    └───────────────────────────────────────┘                                   \n\-        \                                                                                \n\-        \                                                                                \n\-        \You provided the following handlers:                                            \n\-        \                                                                                \n\-        \" <> txt0 <> "\n\-        \                                                                                \n\-        \... which had no matching alternatives in the union you tried to ❰merge❱        \n"-      where-        txt0 = insert (Text.intercalate ", " (Data.Set.toList ks))--prettyTypeMessage (MissingHandler ks) = ErrorMessages {..}-  where-    short = "Missing handler"--    long =-        "Explanation: You can ❰merge❱ the alternatives of a union using a record with one\n\-        \handler per alternative, like this:                                             \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────────────────────────────────────────┐     \n\-        \    │     let union    = < Left = 2 | Right : Bool >                      │     \n\-        \    │ in  let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │     \n\-        \    │ in  merge handlers union : Bool                                     │     \n\-        \    └─────────────────────────────────────────────────────────────────────┘     \n\-        \                                                                                \n\-        \                                                                                \n\-        \... but you must provide exactly one handler per alternative in the union.  You \n\-        \cannot omit any handlers                                                        \n\-        \                                                                                \n\-        \For example, the following expression is " <> _NOT <> " valid:                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \                                              Invalid: Missing ❰Right❱ handler  \n\-        \                                              ⇩                                 \n\-        \    ┌─────────────────────────────────────────────────┐                         \n\-        \    │     let handlers = { Left = Natural/even }      │                         \n\-        \    │ in  let union    = < Left = 2 | Right : Bool >  │                         \n\-        \    │ in  merge handlers union : Bool                 │                         \n\-        \    └─────────────────────────────────────────────────┘                         \n\-        \                                                                                \n\-        \                                                                                \n\-        \Note that you need to provide handlers for other alternatives even if those     \n\-        \alternatives are never used                                                     \n\-        \                                                                                \n\-        \You need to supply the following handlers:                                      \n\-        \                                                                                \n\-        \" <> txt0 <> "\n"-      where-        txt0 = insert (Text.intercalate ", " (Data.Set.toList ks))--prettyTypeMessage MissingMergeType =-    ErrorMessages {..}-  where-    short = "An empty ❰merge❱ requires a type annotation"--    long =-        "Explanation: A ❰merge❱ does not require a type annotation if the union has at   \n\-        \least one alternative, like this                                                \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────────────────────────────────────────┐     \n\-        \    │     let union    = < Left = 2 | Right : Bool >                      │     \n\-        \    │ in  let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │     \n\-        \    │ in  merge handlers union                                            │     \n\-        \    └─────────────────────────────────────────────────────────────────────┘     \n\-        \                                                                                \n\-        \                                                                                \n\-        \However, you must provide a type annotation when merging an empty union:        \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────────────────┐                                          \n\-        \    │ λ(a : <>) → merge {=} a : Bool │                                          \n\-        \    └────────────────────────────────┘                                          \n\-        \                                ⇧                                               \n\-        \                                This can be any type                            \n\-        \                                                                                \n\-        \                                                                                \n\-        \You can provide any type at all as the annotation, since merging an empty       \n\-        \union can produce any type of output                                            \n"--prettyTypeMessage (HandlerInputTypeMismatch expr0 expr1 expr2) =-    ErrorMessages {..}-  where-    short = "Wrong handler input type\n"-        <>  "\n"-        <>  prettyDiff expr1 expr2--    long =-        "Explanation: You can ❰merge❱ the alternatives of a union using a record with one\n\-        \handler per alternative, like this:                                             \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────────────────────────────────────────┐     \n\-        \    │     let union    = < Left = 2 | Right : Bool >                      │     \n\-        \    │ in  let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │     \n\-        \    │ in  merge handlers union : Bool                                     │     \n\-        \    └─────────────────────────────────────────────────────────────────────┘     \n\-        \                                                                                \n\-        \                                                                                \n\-        \... as long as the input type of each handler function matches the type of the  \n\-        \corresponding alternative:                                                      \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────────────────────────────────────┐               \n\-        \    │ union    : < Left : Natural       | Right : Bool        > │               \n\-        \    └───────────────────────────────────────────────────────────┘               \n\-        \                          ⇧                       ⇧                             \n\-        \                   These must match        These must match                     \n\-        \                          ⇩                       ⇩                             \n\-        \    ┌───────────────────────────────────────────────────────────┐               \n\-        \    │ handlers : { Left : Natural → Bool, Right : Bool → Bool } │               \n\-        \    └───────────────────────────────────────────────────────────┘               \n\-        \                                                                                \n\-        \                                                                                \n\-        \For example, the following expression is " <> _NOT <> " valid:                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \      Invalid: Doesn't match the type of the ❰Right❱ alternative                \n\-        \                                                               ⇩                \n\-        \    ┌──────────────────────────────────────────────────────────────────────┐    \n\-        \    │     let handlers = { Left = Natural/even | Right = λ(x : Text) → x } │    \n\-        \    │ in  let union    = < Left = 2 | Right : Bool >                       │    \n\-        \    │ in  merge handlers union : Bool                                      │    \n\-        \    └──────────────────────────────────────────────────────────────────────┘    \n\-        \                                                                                \n\-        \                                                                                \n\-        \Your handler for the following alternative:                                     \n\-        \                                                                                \n\-        \" <> txt0 <> "\n\-        \                                                                                \n\-        \... needs to accept an input value of type:                                     \n\-        \                                                                                \n\-        \" <> txt1 <> "\n\-        \                                                                                \n\-        \... but actually accepts an input value of a different type:                    \n\-        \                                                                                \n\-        \" <> txt2 <> "\n"-      where-        txt0 = insert expr0-        txt1 = insert expr1-        txt2 = insert expr2--prettyTypeMessage (InvalidHandlerOutputType expr0 expr1 expr2) =-    ErrorMessages {..}-  where-    short = "Wrong handler output type\n"-        <>  "\n"-        <>  prettyDiff expr1 expr2--    long =-        "Explanation: You can ❰merge❱ the alternatives of a union using a record with one\n\-        \handler per alternative, like this:                                             \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────────────────────────────────────────┐     \n\-        \    │     let union    = < Left = 2 | Right : Bool >                      │     \n\-        \    │ in  let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │     \n\-        \    │ in  merge handlers union : Bool                                     │     \n\-        \    └─────────────────────────────────────────────────────────────────────┘     \n\-        \                                                                                \n\-        \                                                                                \n\-        \... as long as the output type of each handler function matches the declared    \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 = 2 | Right : Bool >                       │    \n\-        \    │ in  let handlers = { Left = Natural/even, Right = λ(x : Bool) → x }  │    \n\-        \    │ in  merge handlers union : Text                                      │    \n\-        \    └──────────────────────────────────────────────────────────────────────┘    \n\-        \                                 ⇧                                              \n\-        \                                 Invalid: Doesn't match output of either handler\n\-        \                                                                                \n\-        \                                                                                \n\-        \Your handler for the following alternative:                                     \n\-        \                                                                                \n\-        \" <> txt0 <> "\n\-        \                                                                                \n\-        \... needs to return an output value of type:                                    \n\-        \                                                                                \n\-        \" <> txt1 <> "\n\-        \                                                                                \n\-        \... but actually returns an output value of a different type:                   \n\-        \                                                                                \n\-        \" <> txt2 <> "\n"-      where-        txt0 = 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"-        <>  prettyDiff expr0 expr1--    long =-        "Explanation: You can ❰merge❱ the alternatives of a union using a record with one\n\-        \handler per alternative, like this:                                             \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────────────────────────────────────────┐     \n\-        \    │     let union    = < Left = 2 | Right : Bool >                      │     \n\-        \    │ in  let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │     \n\-        \    │ in  merge handlers union                                            │     \n\-        \    └─────────────────────────────────────────────────────────────────────┘     \n\-        \                                                                                \n\-        \                                                                                \n\-        \... as long as the output type of each handler function is the same:            \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────────────────────────────────────┐               \n\-        \    │ handlers : { Left : Natural → Bool, Right : Bool → Bool } │               \n\-        \    └───────────────────────────────────────────────────────────┘               \n\-        \                                    ⇧                    ⇧                      \n\-        \                                These output types both match                   \n\-        \                                                                                \n\-        \                                                                                \n\-        \For example, the following expression is " <> _NOT <> " valid:                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────────────────────┐                         \n\-        \    │     let union    = < Left = 2 | Right : Bool >  │                         \n\-        \    │ in  let handlers =                              │                         \n\-        \    │              { Left  = λ(x : Natural) → x       │  This outputs ❰Natural❱ \n\-        \    │              , Right = λ(x : Bool   ) → x       │  This outputs ❰Bool❱    \n\-        \    │              }                                  │                         \n\-        \    │ in  merge handlers union                        │                         \n\-        \    └─────────────────────────────────────────────────┘                         \n\-        \                ⇧                                                               \n\-        \                Invalid: The handlers in this record don't have matching outputs\n\-        \                                                                                \n\-        \                                                                                \n\-        \The handler for the ❰" <> txt0 <> "❱ alternative has this output type:          \n\-        \                                                                                \n\-        \" <> txt1 <> "\n\-        \                                                                                \n\-        \... but the handler for the ❰" <> txt2 <> "❱ alternative has this output type instead:\n\-        \                                                                                \n\-        \" <> txt3 <> "\n"-      where-        txt0 = pretty key0-        txt1 = insert expr0-        txt2 = pretty key1-        txt3 = insert expr1--prettyTypeMessage (HandlerNotAFunction k expr0) = ErrorMessages {..}-  where-    short = "Handler is not a function"--    long =-        "Explanation: You can ❰merge❱ the alternatives of a union using a record with one\n\-        \handler per alternative, like this:                                             \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────────────────────────────────────────┐     \n\-        \    │     let union    = < Left = 2 | Right : Bool >                      │     \n\-        \    │ in  let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │     \n\-        \    │ in  merge handlers union : Bool                                     │     \n\-        \    └─────────────────────────────────────────────────────────────────────┘     \n\-        \                                                                                \n\-        \                                                                                \n\-        \... as long as each handler is a function                                       \n\-        \                                                                                \n\-        \For example, the following expression is " <> _NOT <> " valid:                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────────────┐                                 \n\-        \    │ merge { Foo = True } < Foo = 1 > : Bool │                                 \n\-        \    └─────────────────────────────────────────┘                                 \n\-        \                    ⇧                                                           \n\-        \                    Invalid: Not a function                                     \n\-        \                                                                                \n\-        \                                                                                \n\-        \Your handler for this alternative:                                              \n\-        \                                                                                \n\-        \" <> txt0 <> "\n\-        \                                                                                \n\-        \... has the following type:                                                     \n\-        \                                                                                \n\-        \" <> txt1 <> "\n\-        \                                                                                \n\-        \... which is not the type of a function                                         \n"-      where-        txt0 = insert k-        txt1 = insert expr0--prettyTypeMessage (ConstructorsRequiresAUnionType expr0 expr1) = ErrorMessages {..}-  where-    short = "❰constructors❱ requires a union type"--    long =-        "Explanation: You can only use the ❰constructors❱ keyword on an argument that is \n\-        \a union type literal, like this:                                                \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────────────────────────┐                           \n\-        \    │ constructors < Left : Natural, Right : Bool > │                           \n\-        \    └───────────────────────────────────────────────┘                           \n\-        \                                                                                \n\-        \                                                                                \n\-        \... but you cannot use the ❰constructors❱ keyword on any other type of argument.\n\-        \For example, you cannot use a variable argument:                                \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────────────────────────┐                                            \n\-        \    │ λ(t : Type) → constructors t │  Invalid: ❰t❱ might not be a union type    \n\-        \    └──────────────────────────────┘                                            \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────────────────────┐                         \n\-        \    │ let t : Type = < Left : Natural, Right : Bool > │  Invalid: Type-checking \n\-        \    │ in  constructors t                              │  precedes normalization \n\-        \    └─────────────────────────────────────────────────┘                         \n\-        \                                                                                \n\-        \                                                                                \n\-        \However, you can import the union type argument:                                \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────────────────┐                                          \n\-        \    │ constructors ./unionType.dhall │ Valid: Import resolution precedes        \n\-        \    └────────────────────────────────┘ type-checking                            \n\-        \                                                                                \n\-        \                                                                                \n\-        \────────────────────────────────────────────────────────────────────────────────\n\-        \                                                                                \n\-        \You tried to supply the following argument:                                     \n\-        \                                                                                \n\-        \" <> txt0 <> "\n\-        \                                                                                \n\-        \... which normalized to:                                                        \n\-        \                                                                                \n\-        \" <> txt1 <> "\n\-        \                                                                                \n\-        \... which is not a union type literal                                           \n"-      where-        txt0 = insert expr0-        txt1 = insert expr1--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"--    long =-        "Explanation: You can only access fields on records, like this:                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────┐                                         \n\-        \    │ { foo = True, bar = \"ABC\" }.foo │  This is valid ...                    \n\-        \    └─────────────────────────────────┘                                         \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────────────────────┐                               \n\-        \    │ λ(r : { foo : Bool, bar : Text }) → r.foo │  ... and so is this           \n\-        \    └───────────────────────────────────────────┘                               \n\-        \                                                                                \n\-        \                                                                                \n\-        \... but you can only access fields if they are present                          \n\-        \                                                                                \n\-        \For example, the following expression is " <> _NOT <> " valid:                  \n\-        \                                                                                \n\-        \    ┌─────────────────────────────────┐                                         \n\-        \    │ { foo = True, bar = \"ABC\" }.qux │                                       \n\-        \    └─────────────────────────────────┘                                         \n\-        \                                  ⇧                                             \n\-        \                                  Invalid: the record has no ❰qux❱ field        \n\-        \                                                                                \n\-        \You tried to access a field named:                                              \n\-        \                                                                                \n\-        \" <> txt0 <> "\n\-        \                                                                                \n\-        \... but the field is missing because the record only defines the following      \n\-        \fields:                                                                         \n\-        \                                                                                \n\-        \" <> txt1 <> "\n"-      where-        txt0 = insert k-        txt1 = insert expr0--prettyTypeMessage (CantAnd expr0 expr1) =-        buildBooleanOperator "&&" expr0 expr1--prettyTypeMessage (CantOr expr0 expr1) =-        buildBooleanOperator "||" expr0 expr1--prettyTypeMessage (CantEQ expr0 expr1) =-        buildBooleanOperator "==" expr0 expr1--prettyTypeMessage (CantNE expr0 expr1) =-        buildBooleanOperator "!=" expr0 expr1--prettyTypeMessage (CantInterpolate expr0 expr1) = ErrorMessages {..}-  where-    short = "You can only interpolate ❰Text❱"--    long =-        "Explanation: Text interpolation only works on expressions of type ❰Text❱        \n\-        \                                                                                \n\-        \For example, these are all valid uses of string interpolation:                  \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌──────────────────┐                                                        \n\-        \    │ \"ABC${\"DEF\"}GHI\" │                                                        \n\-        \    └──────────────────┘                                                        \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌────────────────────────────┐                                              \n\-        \    │ λ(x : Text) → \"ABC${x}GHI\" │                                              \n\-        \    └────────────────────────────┘                                              \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────────────────────────┐                           \n\-        \    │ λ(age : Natural) → \"Age: ${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--prettyTypeMessage (NoDependentTypes expr0 expr1) = ErrorMessages {..}-  where-    short = "No dependent types"--    long =-        "Explanation: The Dhall programming language does not allow functions from terms \n\-        \to types.  These function types are also known as “dependent function types”    \n\-        \because you have a type whose value “depends” on the value of a term.           \n\-        \                                                                                \n\-        \For example, this is " <> _NOT <> " a legal function type:                      \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌─────────────┐                                                             \n\-        \    │ Bool → Type │                                                             \n\-        \    └─────────────┘                                                             \n\-        \                                                                                \n\-        \                                                                                \n\-        \Similarly, this is " <> _NOT <> " legal code:                                   \n\-        \                                                                                \n\-        \                                                                                \n\-        \    ┌───────────────────────────────────────────────────┐                       \n\-        \    │ λ(Vector : Natural → Type → Type) → Vector 0 Text │                       \n\-        \    └───────────────────────────────────────────────────┘                       \n\-        \                 ⇧                                                              \n\-        \                 Invalid dependent type                                         \n\-        \                                                                                \n\-        \                                                                                \n\-        \Your function type is invalid because the input has type:                       \n\-        \                                                                                \n\-        \" <> txt0 <> "\n\-        \                                                                                \n\-        \... and the output has kind:                                                    \n\-        \                                                                                \n\-        \" <> txt1 <> "\n\-        \                                                                                \n\-        \... which makes this a forbidden dependent function type                        \n"-      where-        txt0 = insert expr0-        txt1 = insert 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, ToTerm a) => Show (TypeError s a) where-    show = Pretty.renderString . Pretty.layoutPretty layoutOpts . Pretty.pretty--instance (Eq a, Pretty s, Pretty a, ToTerm a, Typeable s, Typeable a) => Exception (TypeError s a)--instance (Eq a, Pretty s, Pretty a, ToTerm a) => Pretty (TypeError s a) where-    pretty (TypeError ctx expr msg)-        = Pretty.unAnnotate-            (   "\n"-            <>  (   if null (Dhall.Context.toList ctx)-                    then ""-                    else prettyContext ctx <> "\n\n"-                )-            <>  shortTypeMessage msg <> "\n"-            <>  source-            )-      where-        prettyKV (key, val) =-            pretty key <> " : " <> Dhall.Util.snipDoc (pretty val)--        prettyContext =-                Pretty.vsep-            .   map prettyKV-            .   reverse-            .   Dhall.Context.toList--        source = case expr of-            Note s _ -> pretty s-            _        -> mempty--{-| Newtype used to wrap error messages so that they render with a more-    detailed explanation of what went wrong--}-newtype DetailedTypeError s a = DetailedTypeError (TypeError s a)-    deriving (Typeable)--instance (Eq a, Pretty s, Pretty a, ToTerm a) => Show (DetailedTypeError s a) where-    show = Pretty.renderString . Pretty.layoutPretty layoutOpts . Pretty.pretty--instance (Eq a, Pretty s, Pretty a, ToTerm a, Typeable s, Typeable a) => Exception (DetailedTypeError s a)--instance (Eq a, Pretty s, Pretty a, ToTerm a) => Pretty (DetailedTypeError s a) where-    pretty (DetailedTypeError (TypeError ctx expr msg))-        = Pretty.unAnnotate-            (   "\n"-            <>  (   if null (Dhall.Context.toList ctx)-                    then ""-                    else prettyContext ctx <> "\n\n"-                )-            <>  longTypeMessage msg <> "\n"-            <>  "────────────────────────────────────────────────────────────────────────────────\n"-            <>  "\n"-            <>  source-            )-      where-        prettyKV (key, val) =-            pretty key <> " : " <> Dhall.Util.snipDoc (pretty 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 ()+{-# LANGUAGE DeriveDataTypeable  #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE RankNTypes          #-}+{-# LANGUAGE RecordWildCards     #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE ViewPatterns        #-}++{-# OPTIONS_GHC -Wall #-}++-- | This module contains the logic for type checking Dhall code++module Dhall.TypeCheck (+    -- * Type-checking+      typeWith+    , typeOf+    , typeWithA+    , checkContext+    , messageExpressions++    -- * Types+    , Typer+    , X+    , absurd+    , TypeError(..)+    , DetailedTypeError(..)+    , Censored(..)+    , TypeMessage(..)+    , prettyTypeMessage+    , ErrorMessages(..)+    ) where++import Control.Exception                 (Exception)+import Control.Monad.Trans.Class         (lift)+import Control.Monad.Trans.Writer.Strict (execWriterT, tell)+import Data.List.NonEmpty                (NonEmpty (..))+import Data.Monoid                       (Endo (..))+import Data.Semigroup                    (Max (..))+import Data.Sequence                     (ViewL (..))+import Data.Set                          (Set)+import Data.Text                         (Text)+import Data.Typeable                     (Typeable)+import Data.Void                         (Void, absurd)+import Dhall.Context                     (Context)+import Dhall.Eval+    ( Environment (..)+    , Names (..)+    , Val (..)+    , (~>)+    )+import Dhall.Pretty                      (Ann, UnescapedLabel (..))+import Dhall.Src                         (Src)+import Lens.Micro                        (anyOf, over)+import Prettyprinter                     (Doc, Pretty (..), vsep)++import Dhall.Syntax+    ( Binding (..)+    , Chunks (..)+    , Const (..)+    , Expr (..)+    , FunctionBinding (..)+    , PreferAnnotation (..)+    , RecordField (..)+    , Var (..)+    , WithComponent (..)+    )++import qualified Data.Foldable               as Foldable+import qualified Data.Foldable.WithIndex     as Foldable.WithIndex+import qualified Data.List.NonEmpty          as NonEmpty+import qualified Data.Map+import qualified Data.Sequence+import qualified Data.Set+import qualified Data.Text                   as Text+import qualified Data.Traversable+import qualified Dhall.Context+import qualified Dhall.Core+import qualified Dhall.Diff+import qualified Dhall.Eval                  as Eval+import qualified Dhall.Map+import qualified Dhall.Pretty+import qualified Dhall.Pretty.Internal+import qualified Dhall.Syntax                as Syntax+import qualified Dhall.Util+import qualified Prettyprinter               as Pretty+import qualified Prettyprinter.Render.String as Pretty++{-| A type synonym for `Void`++    This is provided for backwards compatibility, since Dhall used to use its+    own `X` type instead of @"Data.Void".`Void`@.  You should use `Void` instead+    of `X` now+-}+type X = Void+{-# DEPRECATED X "Use Data.Void.Void instead" #-}++axiom :: Const -> Either (TypeError s a) Const+axiom Type = return Kind+axiom Kind = return Sort+axiom Sort = Left (TypeError Dhall.Context.empty (Const Sort) Untyped)++rule :: Const -> Const -> Const+rule Type Type = Type+rule Kind Type = Type+rule Sort Type = Type+rule Type Kind = Kind+rule Kind Kind = Kind+rule Sort Kind = Sort+rule Type Sort = Sort+rule Kind Sort = Sort+rule Sort Sort = Sort++{-| Type-check an expression and return the expression's type if type-checking+    succeeds or an error if type-checking fails++    `typeWith` does not necessarily normalize the type since full normalization+    is not necessary for just type-checking.  If you actually care about the+    returned type then you may want to `Dhall.Core.normalize` it afterwards.++    The supplied `Context` records the types of the names in scope. If+    these are ill-typed, the return value may be ill-typed.+-}+typeWith :: Context (Expr s X) -> Expr s X -> Either (TypeError s X) (Expr s X)+typeWith ctx expr = do+    checkContext ctx+    typeWithA absurd ctx expr++{-| Function that converts the value inside an `Embed` constructor into a new+    expression+-}+type Typer a = forall s. a -> Expr s a++{-| Generalization of `typeWith` that allows type-checking the `Embed`+    constructor with custom logic+-}+typeWithA+    :: (Eq a, Pretty a)+    => Typer a+    -> Context (Expr s a)+    -> Expr s a+    -> Either (TypeError s a) (Expr s a)+typeWithA tpa context expression =+    fmap (Dhall.Core.renote . Eval.quote EmptyNames) (infer tpa ctx expression)+  where+    ctx = contextToCtx context++contextToCtx :: Eq a => Context (Expr s a) -> Ctx a+contextToCtx context = loop (Dhall.Context.toList context)+  where+    loop [] =+        Ctx Empty TypesEmpty++    loop ((x, t):rest) =+        Ctx (Skip vs x) (TypesBind ts x (Eval.eval vs (Dhall.Core.denote t)))+      where+        Ctx vs ts = loop rest++ctxToContext :: Eq a => Ctx a -> Context (Expr s a)+ctxToContext (Ctx {..}) = loop types+  where+    loop (TypesBind ts x t) = Dhall.Context.insert x t' (loop ts)+      where+        ns = typesToNames ts++        t' = Dhall.Core.renote (Eval.quote ns t)+    loop TypesEmpty = Dhall.Context.empty++typesToNames :: Types a -> Names+typesToNames (TypesBind ts x _) = Bind ns x+  where+    ns = typesToNames ts+typesToNames TypesEmpty = EmptyNames++data Types a = TypesEmpty | TypesBind !(Types a) {-# UNPACK #-} !Text (Val a)++data Ctx a = Ctx { values :: !(Environment a), types :: !(Types a) }++addType :: Text -> Val a -> Ctx a -> Ctx a+addType x t (Ctx vs ts) = Ctx (Skip vs x) (TypesBind ts x t)++addTypeValue :: Text -> Val a -> Val a -> Ctx a -> Ctx a+addTypeValue x t v (Ctx vs ts) = Ctx (Extend vs x v) (TypesBind ts x t)++fresh :: Ctx a -> Text -> Val a+fresh Ctx{..} x = VVar x (Eval.countNames x (Eval.envNames values))++{-| `typeWithA` is implemented internally in terms of @infer@ in order to speed+    up equivalence checking.++    Specifically, we extend the `Context` to become a @Ctx@, which can store+    the entire contents of a `let` expression (i.e. the type *and* the value+    of the bound variable).  By storing this extra information in the @Ctx@ we+    no longer need to substitute `let` expressions at all (which is very+    expensive!).++    However, this means that we need to use `Dhall.Eval.conv` to perform+    equivalence checking instead of `Dhall.Core.judgmentallyEqual` since+    only `Dhall.Core.judgmentallyEqual` is unable to use the information stored+    in the extended context for accurate equivalence checking.+-}+infer+    :: forall a s+    .  (Eq a, Pretty a)+    => Typer a+    -> Ctx a+    -> Expr s a+    -> Either (TypeError s a) (Val a)+infer typer = loop+  where+    {- The convention for primes (i.e. `'`s) is:++       * No primes  (`x`  ): An `Expr` that has not been `eval`ed yet+       * One prime  (`x'` ): A  `Val`+       * Two primes (`x''`): An `Expr` generated from `quote`ing a `Val`+    -}+    loop :: Ctx a -> Expr s a -> Either (TypeError s a) (Val a)+    loop ctx@Ctx{..} expression = case expression of+        Const c ->+            fmap VConst (axiom c)++        Var (V x0 n0) -> do+            let go TypesEmpty _ =+                    die (UnboundVariable x0)+                go (TypesBind ts x t) n+                    | x == x0   = if n == 0 then return t else go ts (n - 1)+                    | otherwise = go ts n++            go types n0++        Lam _ (FunctionBinding { functionBindingVariable = x, functionBindingAnnotation = _A}) b -> do+            tA' <- loop ctx _A++            case tA' of+                VConst _ -> return ()+                _        -> die (InvalidInputType _A)++            let _A' = eval values _A++            let ctx' = addType x _A' ctx++            _B' <- loop ctx' b++            let _B'' = quote (Bind (Eval.envNames values) x) _B'++            tB' <- loop ctx' (Dhall.Core.renote _B'')++            case tB' of+                VConst _ -> return ()+                _        -> die (InvalidOutputType _B'')++            return (VHPi x _A' (\u -> Eval.eval (Extend values x u) _B''))++        Pi _ x _A _B -> do+            tA' <- loop ctx _A++            kA <- case tA' of+                VConst kA -> return kA+                _         -> die (InvalidInputType _A)++            let _A' = eval values _A++            let ctx' = addType x _A' ctx++            tB' <- loop ctx' _B++            kB <- case tB' of+                VConst kB -> return kB+                _         -> die (InvalidOutputType _B)++            return (VConst (rule kA kB))++        App f a -> do+            tf' <- loop ctx f++            case Eval.toVHPi tf' of+                Just (_x, _A₀', _B') -> do+                    _A₁' <- loop ctx a++                    if Eval.conv values _A₀' _A₁'+                        then do+                            let a' = eval values a++                            return (_B' a')++                        else do+                            let _A₀'' = quote names _A₀'+                            let _A₁'' = quote names _A₁'+                            die (TypeMismatch f _A₀'' a _A₁'')+                Nothing ->+                    die (NotAFunction f (quote names tf'))++        Let (Binding { value = a₀, variable = x, ..}) body -> do+            let a₀' = eval values a₀++            ctxNew <- case annotation of+                Nothing -> do+                    _A' <- loop ctx a₀++                    return (addTypeValue x _A' a₀' ctx)+                Just (_, _A₀) -> do+                    _ <- loop ctx _A₀++                    let _A₀' = eval values _A₀++                    _A₁' <- loop ctx a₀++                    if Eval.conv values _A₀' _A₁'+                        then+                            return ()++                        else do+                            let _A₀'' = quote names _A₀'+                            let _A₁'' = quote names _A₁'+                            Left (TypeError context a₀ (AnnotMismatch a₀ _A₀'' _A₁''))++                    return (addTypeValue x _A₀' a₀' ctx)++            loop ctxNew body++        Annot t _T₀ -> do+            case Dhall.Core.denote _T₀ of+                Const _ -> return ()+                _       -> do+                    _ <- loop ctx _T₀++                    return ()++            let _T₀' = eval values _T₀++            _T₁' <- loop ctx t++            if Eval.conv values _T₀' _T₁'+                then+                    return _T₁'++                else do+                    let _T₀'' = quote names _T₀'+                    let _T₁'' = quote names _T₁'+                    die (AnnotMismatch t _T₀'' _T₁'')++        Bool ->+            return (VConst Type)++        BoolLit _ ->+            return VBool++        BoolAnd l r -> do+            tl' <- loop ctx l++            case tl' of+                VBool -> return ()+                _     -> die (CantAnd l (quote names tl'))++            tr' <- loop ctx r++            case tr' of+                VBool -> return ()+                _     -> die (CantAnd r (quote names tr'))++            return VBool++        BoolOr l r -> do+            tl' <- loop ctx l++            case tl' of+                VBool -> return ()+                _     -> die (CantOr l (quote names tl'))++            tr' <- loop ctx r++            case tr' of+                VBool -> return ()+                _     -> die (CantOr r (quote names tr'))++            return VBool++        BoolEQ l r -> do+            tl' <- loop ctx l++            case tl' of+                VBool -> return ()+                _     -> die (CantEQ l (quote names tl'))++            tr' <- loop ctx r++            case tr' of+                VBool -> return ()+                _     -> die (CantEQ r (quote names tr'))++            return VBool++        BoolNE l r -> do+            tl' <- loop ctx l++            case tl' of+                VBool -> return ()+                _     -> die (CantNE l (quote names tl'))++            tr' <- loop ctx r++            case tr' of+                VBool -> return ()+                _     -> die (CantNE r (quote names tr'))++            return VBool++        BoolIf t l r -> do+            tt' <- loop ctx t++            case tt' of+                VBool -> return ()+                _     -> die (InvalidPredicate t (quote names tt'))++            _L' <- loop ctx l++            _R' <- loop ctx r++            _ <- loop ctx (quote names _L')++            let _L'' = quote names _L'++            _ <- loop ctx (quote names _R')++            let _R'' = quote names _R'++            if Eval.conv values _L' _R'+                then return ()+                else die (IfBranchMismatch l r _L'' _R'')++            return _L'++        Bytes ->+            return (VConst Type)++        BytesLit _ ->+            return VBytes++        Natural ->+            return (VConst Type)++        NaturalLit _ ->+            return VNatural++        NaturalFold ->+            return+                (   VNatural+                ~>  VHPi "natural" (VConst Type) (\natural ->+                        VHPi "succ" (natural ~> natural) (\_succ ->+                            VHPi "zero" natural (\_zero ->+                                natural+                            )+                        )+                    )+                )++        NaturalBuild ->+            return+                (   VHPi "natural" (VConst Type) (\natural ->+                        VHPi "succ" (natural ~> natural) (\_succ ->+                            VHPi "zero" natural (\_zero ->+                                natural+                            )+                        )+                    )+                ~>  VNatural+                )++        NaturalIsZero ->+            return (VNatural ~> VBool)++        NaturalEven ->+            return (VNatural ~> VBool)++        NaturalOdd ->+            return (VNatural ~> VBool)++        NaturalToInteger ->+            return (VNatural ~> VInteger)++        NaturalShow ->+            return (VNatural ~> VText)++        NaturalSubtract ->+            return (VNatural ~> VNatural ~> VNatural)++        NaturalPlus l r -> do+            tl' <- loop ctx l++            case tl' of+                VNatural -> return ()+                _        -> die (CantAdd l (quote names tl'))++            tr' <- loop ctx r++            case tr' of+                VNatural -> return ()+                _        -> die (CantAdd r (quote names tr'))++            return VNatural++        NaturalTimes l r -> do+            tl' <- loop ctx l++            case tl' of+                VNatural -> return ()+                _        -> die (CantMultiply l (quote names tl'))++            tr' <- loop ctx r++            case tr' of+                VNatural -> return ()+                _        -> die (CantMultiply r (quote names tr'))++            return VNatural++        Integer ->+            return (VConst Type)++        IntegerLit _ ->+            return VInteger++        IntegerClamp ->+            return (VInteger ~> VNatural)++        IntegerNegate ->+            return (VInteger ~> VInteger)++        IntegerShow ->+            return (VInteger ~> VText)++        IntegerToDouble ->+            return (VInteger ~> VDouble)++        Double ->+            return (VConst Type)++        DoubleLit _ ->+            return VDouble++        DoubleShow ->+            return (VDouble ~> VText)++        Text ->+            return (VConst Type)++        TextLit (Chunks xys _) -> do+            let process (_, y) = do+                    _Y' <- loop ctx y++                    case _Y' of+                        VText -> return ()+                        _     -> die (CantInterpolate y (quote names _Y'))++            mapM_ process xys++            return VText++        TextAppend l r -> do+            tl' <- loop ctx l++            case tl' of+                VText -> return ()+                _     -> die (CantTextAppend l (quote names tl'))++            tr' <- loop ctx r++            case tr' of+                VText -> return ()+                _     -> die (CantTextAppend r (quote names tr'))++            return VText++        TextReplace ->+            return+                (   VHPi "needle" VText  (\_needle ->+                        VHPi "replacement" VText (\_replacement ->+                            VHPi "haystack" VText (\_haystack ->+                                VText+                            )+                        )+                    )+                )+        TextShow ->+            return (VText ~> VText)++        Date ->+            return (VConst Type)++        DateLiteral _ ->+            return VDate++        DateShow ->+            return (VDate ~> VText)++        Time ->+            return (VConst Type)++        TimeLiteral _ _ ->+            return VTime++        TimeShow ->+            return (VTime ~> VText)++        TimeZone ->+            return (VConst Type)++        TimeZoneLiteral _ ->+            return VTimeZone++        TimeZoneShow ->+            return (VTimeZone ~> VText)++        List ->+            return (VConst Type ~> VConst Type)++        ListLit Nothing ts₀ ->+            case Data.Sequence.viewl ts₀ of+                t₀ :< ts₁ -> do+                    _T₀' <- loop ctx t₀++                    let _T₀'' = quote names _T₀'++                    tT₀' <- loop ctx _T₀''++                    case tT₀' of+                        VConst Type -> return ()+                        _           -> die (InvalidListType (App List _T₀''))++                    let process i t₁ = do+                            _T₁' <- loop ctx t₁++                            if Eval.conv values _T₀' _T₁'+                                then+                                    return ()++                                else do+                                    let _T₀'' = quote names _T₀'+                                    let _T₁'' = quote names _T₁'++                                    -- Carefully note that we don't use `die`+                                    -- here so that the source span is narrowed+                                    -- to just the offending element+                                    let err = MismatchedListElements (i+1) _T₀'' t₁ _T₁''++                                    Left (TypeError context t₁ err)++                    Foldable.WithIndex.itraverse_ process ts₁++                    return (VList _T₀')++                _ ->+                    die MissingListType++        ListLit (Just _T₀) ts ->+            if Data.Sequence.null ts+                then do+                    _ <- loop ctx _T₀++                    let _T₀' = eval values _T₀++                    let _T₀'' = quote names _T₀'++                    case _T₀' of+                        VList _ -> return _T₀'+                        _       -> die (InvalidListType _T₀'')++                -- See https://github.com/dhall-lang/dhall-haskell/issues/1359.+                else die ListLitInvariant++        ListAppend x y -> do+            tx' <- loop ctx x++            _A₀' <- case tx' of+                VList _A₀' -> return _A₀'+                _          -> die (CantListAppend x (quote names tx'))++            ty' <- loop ctx y++            _A₁' <- case ty' of+                VList _A₁' -> return _A₁'+                _          -> die (CantListAppend y (quote names ty'))++            if Eval.conv values _A₀' _A₁'+                then return ()+                else do+                    let _A₀'' = quote names _A₀'+                    let _A₁'' = quote names _A₁'+                    die (ListAppendMismatch _A₀'' _A₁'')++            return (VList _A₀')++        ListBuild ->+            return+                (   VHPi "a" (VConst Type) (\a ->+                            VHPi "list" (VConst Type) (\list ->+                                VHPi "cons" (a ~> list ~> list) (\_cons ->+                                    (VHPi "nil" list (\_nil -> list))+                                )+                            )+                        ~>  VList a+                    )+                )++        ListFold ->+            return+                (   VHPi "a" (VConst Type) (\a ->+                            VList a+                        ~>  VHPi "list" (VConst Type) (\list ->+                                VHPi "cons" (a ~> list ~> list) (\_cons ->+                                    (VHPi "nil" list (\_nil -> list))+                                )+                            )+                    )+                )++        ListLength ->+            return (VHPi "a" (VConst Type) (\a -> VList a ~> VNatural))++        ListHead ->+            return (VHPi "a" (VConst Type) (\a -> VList a ~> VOptional a))++        ListLast ->+            return (VHPi "a" (VConst Type) (\a -> VList a ~> VOptional a))++        ListIndexed ->+            return+                (   VHPi "a" (VConst Type) (\a ->+                            VList a+                        ~>  VList+                                (VRecord+                                    (Dhall.Map.unorderedFromList+                                        [ ("index", VNatural)+                                        , ("value", a       )+                                        ]+                                    )+                                )+                    )+                )+        ListReverse ->+            return (VHPi "a" (VConst Type) (\a -> VList a ~> VList a))++        Optional ->+            return (VConst Type ~> VConst Type)++        None ->+            return (VHPi "A" (VConst Type) (\_A -> VOptional _A))++        Some a -> do+            _A' <- loop ctx a++            tA' <- loop ctx (quote names _A')++            case tA' of+                VConst Type -> return ()+                _           -> do+                   let _A'' = quote names _A'+                   let tA'' = quote names tA'++                   die (InvalidSome a _A'' tA'')++            return (VOptional _A')++        Record xTs -> do+            let process x (RecordField {recordFieldValue = _T}) = do+                    tT' <- lift (loop ctx _T)++                    case tT' of+                        VConst c -> tell (Max c)+                        _        -> lift (die (InvalidFieldType x _T))++            Max c <- execWriterT (Dhall.Map.unorderedTraverseWithKey_ process xTs)++            return (VConst c)++        RecordLit xts -> do+            let process t = do+                    _T' <- loop ctx $ recordFieldValue t++                    let _T'' = quote names _T'++                    _ <- loop ctx _T''++                    return _T'++            xTs <- traverse process (Dhall.Map.sort xts)++            return (VRecord xTs)++        Union xTs -> do+            let process _ Nothing =+                    return mempty++                process x₁ (Just _T₁) = do+                    tT₁' <- loop ctx _T₁++                    case tT₁' of+                        VConst c -> return (Max c)+                        _        -> die (InvalidAlternativeType x₁ _T₁)++            Max c <- fmap Foldable.fold (Dhall.Map.unorderedTraverseWithKey process xTs)+            return (VConst c)+        Combine _ mk l r -> do+            _L' <- loop ctx l++            let l'' = quote names (eval values l)++            _R' <- loop ctx r++            let r'' = quote names (eval values r)++            xLs' <- case _L' of+                VRecord xLs' ->+                    return xLs'++                _ -> do+                    let _L'' = quote names _L'++                    case mk of+                        Nothing -> die (MustCombineARecord '∧' l'' _L'')+                        Just t  -> die (InvalidDuplicateField t l _L'')++            xRs' <- case _R' of+                VRecord xRs' ->+                    return xRs'++                _ -> do+                    let _R'' = quote names _R'++                    case mk of+                        Nothing -> die (MustCombineARecord '∧' r'' _R'')+                        Just t  -> die (InvalidDuplicateField t r _R'')++            let combineTypes xs xLs₀' xRs₀' = do+                    let combine x (VRecord xLs₁') (VRecord xRs₁') =+                            combineTypes (x : xs) xLs₁' xRs₁'++                        combine x _ _ =+                            case mk of+                                Nothing -> die (FieldCollision (NonEmpty.reverse (x :| xs)))+                                Just t  -> die (DuplicateFieldCannotBeMerged (t :| reverse (x : xs)))++                    let xEs =+                            Dhall.Map.outerJoin Right Right combine xLs₀' xRs₀'++                    xTs <- Dhall.Map.unorderedTraverseWithKey (\_x _E -> _E) xEs++                    return (VRecord xTs)++            combineTypes [] xLs' xRs'++        CombineTypes _ l r -> do+            _L' <- loop ctx l++            let l' = eval values l++            let l'' = quote names l'++            cL <- case _L' of+                VConst cL -> return cL+                _         -> die (CombineTypesRequiresRecordType l l'')++            _R' <- loop ctx r++            let r' = eval values r++            let r'' = quote names r'++            cR <- case _R' of+                VConst cR -> return cR+                _         -> die (CombineTypesRequiresRecordType r r'')++            let c = max cL cR++            xLs' <- case l' of+                VRecord xLs' -> return xLs'+                _            -> die (CombineTypesRequiresRecordType l l'')++            xRs' <- case r' of+                VRecord xRs' -> return xRs'+                _            -> die (CombineTypesRequiresRecordType r r'')++            let combineTypes xs xLs₀' xRs₀' = do+                    let combine x (VRecord xLs₁') (VRecord xRs₁') =+                            combineTypes (x : xs) xLs₁' xRs₁'++                        combine x _ _ =+                            die (FieldTypeCollision (NonEmpty.reverse (x :| xs)))++                    let mL = Dhall.Map.toMap xLs₀'+                    let mR = Dhall.Map.toMap xRs₀'++                    Foldable.sequence_ (Data.Map.intersectionWithKey combine mL mR)++            combineTypes [] xLs' xRs'++            return (VConst c)++        Prefer _ _ l r -> do+            _L' <- loop ctx l++            _R' <- loop ctx r++            xLs' <- case _L' of+                VRecord xLs' -> return xLs'++                _            -> do+                    let _L'' = quote names _L'++                    let l'' = quote names (eval values l)++                    die (MustCombineARecord '⫽' l'' _L'')++            xRs' <- case _R' of+                VRecord xRs' -> return xRs'++                _            -> do+                    let _R'' = quote names _R'++                    let r'' = quote names (eval values r)++                    die (MustCombineARecord '⫽' r'' _R'')++            return (VRecord (Dhall.Map.union xRs' xLs'))++        RecordCompletion l r -> do+            _L' <- loop ctx l++            case _L' of+                VRecord xLs'+                  | not (Dhall.Map.member "default" xLs')+                     -> die (InvalidRecordCompletion "default" l)+                  | not (Dhall.Map.member "Type" xLs')+                     -> die (InvalidRecordCompletion "Type" l)+                  | otherwise+                     -> loop ctx (Annot (Prefer mempty PreferFromCompletion (Field l def) r) (Field l typ))+                _ -> die (CompletionSchemaMustBeARecord l (quote names _L'))++              where+                def = Syntax.makeFieldSelection "default"+                typ = Syntax.makeFieldSelection "Type"+        Merge t u mT₁ -> do+            _T' <- loop ctx t++            yTs' <- case _T' of+                VRecord yTs' ->+                    return yTs'++                _ -> do+                    let _T'' = quote names _T'++                    die (MustMergeARecord t _T'')++            _U' <- loop ctx u++            yUs' <- case _U' of+                VUnion yUs' ->+                    return yUs'++                VOptional _O' ->+                    -- This is a bit of hack, but it allows us to reuse the+                    -- rather complex type-matching logic for Optionals.+                    return (Dhall.Map.unorderedFromList [("None", Nothing), ("Some", Just _O')])++                _ -> do+                    let _U'' = quote names _U'++                    die (MustMergeUnionOrOptional u _U'')++            let ysT = Dhall.Map.keysSet yTs'+            let ysU = Dhall.Map.keysSet yUs'++            let diffT = Data.Set.difference ysT ysU+            let diffU = Data.Set.difference ysU ysT++            if Data.Set.null diffT+                then return ()+                else die (UnusedHandler diffT)++            if Data.Set.null diffU+                then return ()+                else let (exemplar,rest) = Data.Set.deleteFindMin diffU+                     in die (MissingHandler exemplar rest)++            let match _y _T₀' Nothing =+                    return _T₀'++                match y handler' (Just _A₁') =+                    case Eval.toVHPi handler' of+                        Just (x, _A₀', _T₀') ->+                            if Eval.conv values _A₀' _A₁'+                                then do+                                    let _T₁' = _T₀' (fresh ctx x)++                                    let _T₁'' = quote names _T₁'++                                    -- x appearing in _T₁'' would indicate a disallowed+                                    -- handler type (see+                                    -- https://github.com/dhall-lang/dhall-lang/issues/749).+                                    --+                                    -- If x appears in _T₁'', quote will have given it index+                                    -- -1. Any well-typed variable has a non-negative index,+                                    -- so we can simply look for negative indices to detect x.+                                    let containsBadVar (Var (V _ n)) =+                                            n < 0++                                        containsBadVar e =+                                            anyOf+                                                Dhall.Core.subExpressions+                                                containsBadVar+                                                e++                                    if containsBadVar _T₁''+                                        then do+                                            let handler'' = quote names handler'++                                            let outputType = Dhall.Core.shift 1 (V x (-1)) _T₁''++                                            die (DisallowedHandlerType y handler'' outputType x)++                                        else return _T₁'++                                else do+                                    let _A₀'' = quote names _A₀'+                                    let _A₁'' = quote names _A₁'++                                    die (HandlerInputTypeMismatch y _A₁'' _A₀'')++                        Nothing -> do+                            let handler'' = quote names handler'++                            die (HandlerNotAFunction y handler'')++            matched <-+                sequence+                    (Data.Map.intersectionWithKey match (Dhall.Map.toMap yTs') (Dhall.Map.toMap yUs'))++            let checkMatched :: Data.Map.Map Text (Val a) -> Either (TypeError s a) (Maybe (Val a))+                checkMatched = fmap (fmap snd) . Foldable.foldlM go Nothing . Data.Map.toList+                  where+                    go Nothing (y₁, _T₁') =+                        return (Just (y₁, _T₁'))++                    go yT₀'@(Just (y₀, _T₀')) (y₁, _T₁') =+                        if Eval.conv values _T₀' _T₁'+                            then return yT₀'++                            else do+                                let _T₀'' = quote names _T₀'+                                let _T₁'' = quote names _T₁'+                                die (HandlerOutputTypeMismatch y₀ _T₀'' y₁ _T₁'')++            mT₀' <- checkMatched matched++            mT₁' <- Data.Traversable.for mT₁ $ \_T₁ -> do+                _ <- loop ctx _T₁++                return (eval values _T₁)++            case (mT₀', mT₁') of+                (Nothing, Nothing) ->+                    die MissingMergeType+                (Nothing, Just _T₁') ->+                    return _T₁'+                (Just _T₀', Nothing) ->+                    return _T₀'+                (Just _T₀', Just _T₁') ->+                    if Eval.conv values _T₀' _T₁'+                        then return _T₀'++                        else do+                            let _T₀'' = quote names _T₀'+                            let _T₁'' = quote names _T₁'+                            die (AnnotMismatch (Merge t u Nothing) _T₁'' _T₀'')++        ToMap e mT₁ -> do+            _E' <- loop ctx e++            let _E'' = quote names _E'++            xTs' <- case _E' of+                VRecord xTs' -> return xTs'+                _            -> die (MustMapARecord e _E'')++            tE' <- loop ctx _E''++            let tE'' = quote names tE'++            case tE' of+                VConst Type -> return ()+                _           -> die (InvalidToMapRecordKind _E'' tE'')++            Foldable.traverse_ (loop ctx) mT₁++            let compareFieldTypes _T₀' Nothing =+                    Just (Right _T₀')++                compareFieldTypes _T₀' r@(Just (Right _T₁'))+                    | Eval.conv values _T₀' _T₁' = r+                    | otherwise = do+                        let _T₀'' = quote names _T₀'+                        let _T₁'' = quote names _T₁'++                        Just (die (HeterogenousRecordToMap _E'' _T₀'' _T₁''))++                compareFieldTypes _T₀' r@(Just (Left _)) =+                    r++            let r = appEndo (foldMap (Endo . compareFieldTypes) xTs') Nothing++            let mT₁' = fmap (eval values) mT₁++            let mapType _T' =+                    VList+                        (VRecord+                            (Dhall.Map.unorderedFromList+                                [("mapKey", VText), ("mapValue", _T')]+                            )+                        )++            case (r, mT₁') of+                (Nothing, Nothing) ->+                    die MissingToMapType+                (Just err@(Left _), _) ->+                    err+                (Just (Right _T'), Nothing) ->+                    pure (mapType _T')+                (Nothing, Just _T₁'@(VList (VRecord itemTypes)))+                   | Just _T' <- Dhall.Map.lookup "mapValue" itemTypes+                   , Eval.conv values (mapType _T') _T₁' ->+                       pure _T₁'+                (Nothing, Just _T₁') -> do+                    let _T₁'' = quote names _T₁'++                    die (InvalidToMapType _T₁'')+                (Just (Right _T'), Just _T₁')+                   | Eval.conv values (mapType _T') _T₁' ->+                       pure (mapType _T')+                   | otherwise -> do+                       let _T₁'' = quote names _T₁'++                       die (MapTypeMismatch (quote names (mapType _T')) _T₁'')++        ShowConstructor e -> do+            _E' <- loop ctx e+            case _E' of+              VUnion _ -> pure VText+              VOptional _ -> pure VText++              _ -> die ShowConstructorNotOnUnion++        Field e (Syntax.fieldSelectionLabel -> x) -> do+            _E' <- loop ctx e++            let _E'' = quote names _E'++            case _E' of+                VRecord xTs' ->+                    case Dhall.Map.lookup x xTs' of+                        Just _T' -> return _T'+                        Nothing  -> die (MissingField x _E'')+                _ -> do+                    let e' = eval values e++                    let e'' = quote names e'++                    case e' of+                        VUnion xTs' ->+                            case Dhall.Map.lookup x xTs' of+                                Just (Just _T') -> return (VHPi x _T' (\_ -> e'))+                                Just  Nothing   -> return e'+                                Nothing         -> die (MissingConstructor x e)++                        _ -> do+                            let text = Dhall.Pretty.Internal.docToStrictText (Dhall.Pretty.Internal.prettyLabel x)++                            die (CantAccess text e'' _E'')+        Project e (Left xs) -> do+            case duplicateElement xs of+                Just x -> do+                    die (DuplicateProjectionLabel x)+                Nothing -> do+                    return ()++            _E' <- loop ctx e++            let _E'' = quote names _E'++            case _E' of+                VRecord xTs' -> do+                    let process x =+                            case Dhall.Map.lookup x xTs' of+                                Just _T' -> return (x, _T')+                                Nothing  -> die (MissingField x _E'')++                    let adapt = VRecord . Dhall.Map.unorderedFromList++                    fmap adapt (traverse process xs)++                _ -> do+                    let text =+                            Dhall.Pretty.Internal.docToStrictText (Dhall.Pretty.Internal.prettyLabels xs)++                    die (CantProject text e _E'')++        Project e (Right s) -> do+            _E' <- loop ctx e++            let _E'' = quote names _E'++            case _E' of+                VRecord xEs' -> do+                    _ <- loop ctx s++                    let s' = eval values s++                    case s' of+                        VRecord xSs' -> do+                            let actualSubset =+                                    quote names (VRecord (Dhall.Map.intersection xEs' xSs'))++                            let expectedSubset = s++                            let process x _S' = do+                                    let _S'' = quote names _S'++                                    case Dhall.Map.lookup x xEs' of+                                        Nothing ->+                                            die (MissingField x _E'')++                                        Just _E' ->+                                            if Eval.conv values _E' _S'+                                                then return ()+                                                else die (ProjectionTypeMismatch x _E'' _S'' expectedSubset actualSubset)++                            Dhall.Map.unorderedTraverseWithKey_ process xSs'++                            return s'++                        _ ->+                            die (CantProjectByExpression s)++                _ -> do+                    let text = Dhall.Core.pretty s++                    die (CantProject text e s)++        Assert _T -> do+            _ <- loop ctx _T++            let _T' = eval values _T++            case _T' of+                VEquivalent x' y' -> do+                    let x'' = quote names x'+                    let y'' = quote names y'++                    if Eval.conv values x' y'+                        then return _T'+                        else die (AssertionFailed x'' y'')++                _ ->+                    die (NotAnEquivalence _T)++        Equivalent _ x y -> do+            _A₀' <- loop ctx x++            let _A₀'' = quote names _A₀'++            tA₀' <- loop ctx _A₀''++            case tA₀' of+                VConst Type -> return ()+                _          -> die (IncomparableExpression x)++            _A₁' <- loop ctx y++            let _A₁'' = quote names _A₁'++            tA₁' <- loop ctx _A₁''++            case tA₁' of+                VConst Type -> return ()+                _           -> die (IncomparableExpression y)++            if Eval.conv values _A₀' _A₁'+                then return ()+                else die (EquivalenceTypeMismatch x _A₀'' y _A₁'')++            return (VConst Type)++        With e₀ ks₀ v₀ -> do+            tE₀' <- loop ctx e₀++            -- The purpose of this inner loop is to ensure that we only need to+            -- typecheck the record once++            let with tE' ks v = case tE' of+                  VRecord kTs' ->+                    case ks of+                      WithLabel k :| [] -> do+                          tV' <- loop ctx v++                          return (VRecord (Dhall.Map.insert k tV' kTs'))+                      WithLabel k₀ :| k₁ : ks' -> do+                          let _T =+                                  case Dhall.Map.lookup k₀ kTs' of+                                      Just _T' -> _T'+                                      Nothing  -> VRecord mempty++                          tV' <- with _T (k₁ :| ks') v++                          return (VRecord (Dhall.Map.insert k₀ tV' kTs'))+                      WithQuestion :| _ -> do+                          die NotALabelPath++                  VOptional _O' -> do+                    case ks of++                        -- (Some x) with ? = v is valid iff the type of x is the same as the type of v.+                      WithQuestion :| [] -> do+                        tV' <- loop ctx v+                        if Eval.conv values _O' tV'+                          then return (VOptional _O')+                          else die OptionalWithTypeMismatch++                        -- (Some x) with ?.a.b = v is valid iff the type of x.a.b is the same as the type of v.+                      WithQuestion :| k₁ : ks' -> do+                        tV' <- with _O' (k₁ :| ks') v+                        if Eval.conv values _O' tV'+                          then return (VOptional _O')+                          else die OptionalWithTypeMismatch++                      WithLabel k :| _ -> die (NotAQuestionPath k)++                  _ -> die (NotWithARecord e₀ (quote names tE')) -- TODO: NotWithARecordOrOptional++            with tE₀' ks₀ v₀++        Note s e ->+            case loop ctx e of+                Left (TypeError ctx' (Note s' e') m) ->+                    Left (TypeError ctx' (Note s' e') m)+                Left (TypeError ctx'          e'  m) ->+                    Left (TypeError ctx' (Note s  e') m)+                Right r ->+                    Right r++        ImportAlt l _r ->+            loop ctx l++        Embed p ->+            return (eval values (typer p))+      where+        die err = Left (TypeError context expression err)++        context = ctxToContext ctx++        names = typesToNames types++        eval vs e = Eval.eval vs (Dhall.Core.denote e)++        quote ns value = Dhall.Core.renote (Eval.quote ns value)++{-| `typeOf` is the same as `typeWith` with an empty context, meaning that the+    expression must be closed (i.e. no free variables), otherwise type-checking+    will fail.+-}+typeOf :: Expr s X -> Either (TypeError s X) (Expr s X)+typeOf = typeWith Dhall.Context.empty++-- | The specific type error+data TypeMessage s a+    = UnboundVariable Text+    | InvalidInputType (Expr s a)+    | InvalidOutputType (Expr s a)+    | NotAFunction (Expr s a) (Expr s a)+    | TypeMismatch (Expr s a) (Expr s a) (Expr s a) (Expr s a)+    | AnnotMismatch (Expr s a) (Expr s a) (Expr s a)+    | Untyped+    | MissingListType+    | MismatchedListElements Int (Expr s a) (Expr s a) (Expr s a)+    | InvalidListType (Expr s a)+    | ListLitInvariant+    | InvalidSome (Expr s a) (Expr s a) (Expr s a)+    | InvalidPredicate (Expr s a) (Expr s a)+    | IfBranchMismatch (Expr s a) (Expr s a) (Expr s a) (Expr s a)+    | InvalidFieldType Text (Expr s a)+    | InvalidAlternativeType Text (Expr s a)+    | ListAppendMismatch (Expr s a) (Expr s a)+    | MustCombineARecord Char (Expr s a) (Expr s a)+    | InvalidDuplicateField Text (Expr s a) (Expr s a)+    | InvalidRecordCompletion Text (Expr s a)+    | CompletionSchemaMustBeARecord (Expr s a) (Expr s a)+    | CombineTypesRequiresRecordType (Expr s a) (Expr s a)+    | DuplicateFieldCannotBeMerged (NonEmpty Text)+    | FieldCollision (NonEmpty Text)+    | FieldTypeCollision (NonEmpty Text)+    | MustMergeARecord (Expr s a) (Expr s a)+    | MustMergeUnionOrOptional (Expr s a) (Expr s a)+    | MustMapARecord (Expr s a) (Expr s a)+    | InvalidToMapRecordKind (Expr s a) (Expr s a)+    | HeterogenousRecordToMap (Expr s a) (Expr s a) (Expr s a)+    | InvalidToMapType (Expr s a)+    | MapTypeMismatch (Expr s a) (Expr s a)+    | MissingToMapType+    | UnusedHandler (Set Text)+    | MissingHandler Text (Set Text)+    | HandlerInputTypeMismatch Text (Expr s a) (Expr s a)+    | DisallowedHandlerType Text (Expr s a) (Expr s a) Text+    | HandlerOutputTypeMismatch Text (Expr s a) Text (Expr s a)+    | MissingMergeType+    | HandlerNotAFunction Text (Expr s a)+    | CantAccess Text (Expr s a) (Expr s a)+    | CantProject Text (Expr s a) (Expr s a)+    | CantProjectByExpression (Expr s a)+    | DuplicateProjectionLabel Text+    | MissingField Text (Expr s a)+    | MissingConstructor Text (Expr s a)+    | ProjectionTypeMismatch Text (Expr s a) (Expr s a) (Expr s a) (Expr s a)+    | AssertionFailed (Expr s a) (Expr s a)+    | NotAnEquivalence (Expr s a)+    | IncomparableExpression (Expr s a)+    | EquivalenceTypeMismatch (Expr s a) (Expr s a) (Expr s a) (Expr s a)+    | NotWithARecord (Expr s a) (Expr s a)+    | CantAnd (Expr s a) (Expr s a)+    | CantOr (Expr s a) (Expr s a)+    | CantEQ (Expr s a) (Expr s a)+    | CantNE (Expr s a) (Expr s a)+    | CantInterpolate (Expr s a) (Expr s a)+    | CantTextAppend (Expr s a) (Expr s a)+    | CantListAppend (Expr s a) (Expr s a)+    | CantAdd (Expr s a) (Expr s a)+    | CantMultiply (Expr s a) (Expr s a)+    | OptionalWithTypeMismatch+    | NotALabelPath+    | NotAQuestionPath Text+    | ShowConstructorNotOnUnion+    deriving (Show)++formatHints :: [Doc Ann] -> Doc Ann+formatHints hints = vsep (map format hints)+  where+    format hint = "\n\n\ESC[1;33mHint\ESC[0m: " <> hint++shortTypeMessage :: (Eq a, Pretty a) => TypeMessage s a -> Doc Ann+shortTypeMessage msg =+    "\ESC[1;31mError\ESC[0m: " <> short <> formatHints hints <> "\n"+  where+    ErrorMessages {..} = prettyTypeMessage msg++longTypeMessage :: (Eq a, Pretty a) => TypeMessage s a -> Doc Ann+longTypeMessage msg =+        "\ESC[1;31mError\ESC[0m: " <> short <> formatHints hints <> "\n"+    <>  "\n"+    <>  long+  where+    ErrorMessages {..} = prettyTypeMessage msg++{-| Output of `prettyTypeMessage`, containing short- and long-form error+    messages+-}+data ErrorMessages = ErrorMessages+    { short :: Doc Ann+    -- ^ Default succinct 1-line explanation of what went wrong+    , hints :: [Doc Ann]+    -- ^ Possibly-empty hints based on specific types involved in the error+    , long  :: Doc Ann+    -- ^ Longer and more detailed explanation of the error+    }++_NOT :: Doc ann+_NOT = "\ESC[1mnot\ESC[0m"++insert :: Pretty a => a -> Doc Ann+insert = Dhall.Util.insert++emptyRecordTypeHint :: (Eq a, Pretty a) => Expr s a -> [Doc Ann]+emptyRecordTypeHint expr =+    if Eval.judgmentallyEqual expr (Record mempty) then+        ["{} is the empty record type, use {=} for the empty record value"]+    else []++-- | Convert a `TypeMessage` to short- and long-form `ErrorMessages`+prettyTypeMessage :: (Eq a, Pretty a) => TypeMessage s a -> ErrorMessages+prettyTypeMessage (UnboundVariable x) = ErrorMessages {..}+  -- We do not need to print variable name here. For the discussion see:+  -- https://github.com/dhall-lang/dhall-haskell/pull/116+  where+    short = "Unbound variable: " <> Pretty.pretty x++    hints = []++    long =+        "Explanation: Expressions can only reference previously introduced (i.e. “bound”)\n\+        \variables that are still “in scope”                                             \n\+        \                                                                                \n\+        \For example, the following valid expressions introduce a “bound” variable named \n\+        \❰x❱:                                                                            \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────┐                                                         \n\+        \    │ λ(x : Bool) → x │  Anonymous functions introduce “bound” variables        \n\+        \    └─────────────────┘                                                         \n\+        \        ⇧                                                                       \n\+        \        This is the bound variable                                              \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────┐                                                         \n\+        \    │ let x = 1 in x  │  ❰let❱ expressions introduce “bound” variables          \n\+        \    └─────────────────┘                                                         \n\+        \          ⇧                                                                     \n\+        \          This is the bound variable                                            \n\+        \                                                                                \n\+        \                                                                                \n\+        \However, the following expressions are not valid because they all reference a   \n\+        \variable that has not been introduced yet (i.e. an “unbound” variable):         \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────┐                                                         \n\+        \    │ λ(x : Bool) → y │  The variable ❰y❱ hasn't been introduced yet            \n\+        \    └─────────────────┘                                                         \n\+        \                    ⇧                                                           \n\+        \                    This is the unbound variable                                \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────┐                                                \n\+        \    │ (let x = True in x) && x │  ❰x❱ is undefined outside the parentheses      \n\+        \    └──────────────────────────┘                                                \n\+        \                             ⇧                                                  \n\+        \                             This is the unbound variable                       \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────┐                                                          \n\+        \    │ let x = x in x │  The definition for ❰x❱ cannot reference itself          \n\+        \    └────────────────┘                                                          \n\+        \              ⇧                                                                 \n\+        \              This is the unbound variable                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● You misspell a variable name, like this:                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────────────────────────────┐                      \n\+        \    │ λ(empty : Bool) → if emty then \"Empty\" else \"Full\" │                      \n\+        \    └────────────────────────────────────────────────────┘                      \n\+        \                           ⇧                                                    \n\+        \                           Typo                                                 \n\+        \                                                                                \n\+        \                                                                                \n\+        \● You misspell a reserved identifier, like this:                                \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────┐                                                \n\+        \    │ foral (a : Type) → a → a │                                                \n\+        \    └──────────────────────────┘                                                \n\+        \      ⇧                                                                         \n\+        \      Typo                                                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \● You tried to define a recursive value, like this:                             \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────┐                                                      \n\+        \    │ let x = x + 1 in x │                                                      \n\+        \    └────────────────────┘                                                      \n\+        \              ⇧                                                                 \n\+        \              Recursive definitions are not allowed                             \n\+        \                                                                                \n\+        \                                                                                \n\+        \● You accidentally forgot a ❰λ❱ or ❰∀❱/❰forall❱                                 \n\+        \                                                                                \n\+        \                                                                                \n\+        \        Unbound variable                                                        \n\+        \        ⇩                                                                       \n\+        \    ┌─────────────────┐                                                         \n\+        \    │  (x : Bool) → x │                                                         \n\+        \    └─────────────────┘                                                         \n\+        \      ⇧                                                                         \n\+        \      A ❰λ❱ here would transform this into a valid anonymous function           \n\+        \                                                                                \n\+        \                                                                                \n\+        \        Unbound variable                                                        \n\+        \        ⇩                                                                       \n\+        \    ┌────────────────────┐                                                      \n\+        \    │  (x : Bool) → Bool │                                                      \n\+        \    └────────────────────┘                                                      \n\+        \      ⇧                                                                         \n\+        \      A ❰∀❱ or ❰forall❱ here would transform this into a valid function type    \n\+        \                                                                                \n\+        \                                                                                \n\+        \● You forgot to prefix a file path with ❰./❱:                                   \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────┐                                                      \n\+        \    │ path/to/file.dhall │                                                      \n\+        \    └────────────────────┘                                                      \n\+        \      ⇧                                                                         \n\+        \      This should be ❰./path/to/file.dhall❱                                     \n"++prettyTypeMessage (InvalidInputType expr) = ErrorMessages {..}+  where+    short = "Invalid function input"++    hints = []++    long =+        "Explanation: A function can accept an input “term” that has a given “type”, like\n\+        \this:                                                                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \        This is the input term that the function accepts                        \n\+        \        ⇩                                                                       \n\+        \    ┌───────────────────────┐                                                   \n\+        \    │ ∀(x : Natural) → Bool │  This is the type of a function that accepts an   \n\+        \    └───────────────────────┘  input term named ❰x❱ that has type ❰Natural❱     \n\+        \            ⇧                                                                   \n\+        \            This is the type of the input term                                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────┐                                                          \n\+        \    │ Bool → Natural │  This is the type of a function that accepts an anonymous\n\+        \    └────────────────┘  input term that has type ❰Bool❱                         \n\+        \      ⇧                                                                         \n\+        \      This is the type of the input term                                        \n\+        \                                                                                \n\+        \                                                                                \n\+        \... or a function can accept an input “type” that has a given “kind”, like this:\n\+        \                                                                                \n\+        \                                                                                \n\+        \        This is the input type that the function accepts                        \n\+        \        ⇩                                                                       \n\+        \    ┌────────────────────┐                                                      \n\+        \    │ ∀(a : Type) → Type │  This is the type of a function that accepts an input\n\+        \    └────────────────────┘  type named ❰a❱ that has kind ❰Type❱                 \n\+        \            ⇧                                                                   \n\+        \            This is the kind of the input type                                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────┐                                                    \n\+        \    │ (Type → Type) → Type │  This is the type of a function that accepts an    \n\+        \    └──────────────────────┘  anonymous input type that has kind ❰Type → Type❱  \n\+        \       ⇧                                                                        \n\+        \       This is the kind of the input type                                       \n\+        \                                                                                \n\+        \                                                                                \n\+        \Other function inputs are " <> _NOT <> " valid, like this:                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────┐                                                            \n\+        \    │ ∀(x : 1) → x │  ❰1❱ is a “term” and not a “type” nor a “kind” so ❰x❱      \n\+        \    └──────────────┘  cannot have “type” ❰1❱ or “kind” ❰1❱                      \n\+        \            ⇧                                                                   \n\+        \            This is not a type or kind                                          \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────┐                                                                \n\+        \    │ True → x │  ❰True❱ is a “term” and not a “type” nor a “kind” so the       \n\+        \    └──────────┘  anonymous input cannot have “type” ❰True❱ or “kind” ❰True❱    \n\+        \      ⇧                                                                         \n\+        \      This is not a type or kind                                                \n\+        \                                                                                \n\+        \                                                                                \n\+        \You annotated a function input with the following expression:                   \n\+        \                                                                                \n\+        \" <> txt <> "\n\+        \                                                                                \n\+        \... which is neither a type nor a kind                                          \n"+      where+        txt = insert expr++prettyTypeMessage (InvalidOutputType expr) = ErrorMessages {..}+  where+    short = "Invalid function output"++    hints = []++    long =+        "Explanation: A function can return an output “term” that has a given “type”,    \n\+        \like this:                                                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────┐                                                      \n\+        \    │ ∀(x : Text) → Bool │  This is the type of a function that returns an      \n\+        \    └────────────────────┘  output term that has type ❰Bool❱                    \n\+        \                    ⇧                                                           \n\+        \                    This is the type of the output term                         \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────┐                                                          \n\+        \    │ Bool → Natural │  This is the type of a function that returns an output   \n\+        \    └────────────────┘  term that has type ❰Natural❱                            \n\+        \             ⇧                                                                  \n\+        \             This is the type of the output term                                \n\+        \                                                                                \n\+        \                                                                                \n\+        \... or a function can return an output “type” that has a given “kind”, like     \n\+        \this:                                                                           \n\+        \                                                                                \n\+        \    ┌────────────────────┐                                                      \n\+        \    │ ∀(a : Type) → Type │  This is the type of a function that returns an      \n\+        \    └────────────────────┘  output type that has kind ❰Type❱                    \n\+        \                    ⇧                                                           \n\+        \                    This is the kind of the output type                         \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────┐                                                    \n\+        \    │ (Type → Type) → Type │  This is the type of a function that returns an    \n\+        \    └──────────────────────┘  output type that has kind ❰Type❱                  \n\+        \                      ⇧                                                         \n\+        \                      This is the kind of the output type                       \n\+        \                                                                                \n\+        \                                                                                \n\+        \Other outputs are " <> _NOT <> " valid, like this:                              \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────┐                                                         \n\+        \    │ ∀(x : Bool) → x │  ❰x❱ is a “term” and not a “type” nor a “kind” so the   \n\+        \    └─────────────────┘  output cannot have “type” ❰x❱ or “kind” ❰x❱            \n\+        \                    ⇧                                                           \n\+        \                    This is not a type or kind                                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────┐                                                             \n\+        \    │ Text → True │  ❰True❱ is a “term” and not a “type” nor a “kind” so the    \n\+        \    └─────────────┘  output cannot have “type” ❰True❱ or “kind” ❰True❱          \n\+        \             ⇧                                                                  \n\+        \             This is not a type or kind                                         \n\+        \                                                                                \n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● You use ❰∀❱ instead of ❰λ❱ by mistake, like this:                             \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────┐                                                          \n\+        \    │ ∀(x: Bool) → x │                                                          \n\+        \    └────────────────┘                                                          \n\+        \      ⇧                                                                         \n\+        \      Using ❰λ❱ here instead of ❰∀❱ would transform this into a valid function  \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You specified that your function outputs a:                                     \n\+        \                                                                                \n\+        \" <> txt <> "\n\+        \                                                                                \n\+        \... which is neither a type nor a kind:                                         \n"+      where+        txt = insert expr++prettyTypeMessage (NotAFunction expr0 expr1) = ErrorMessages {..}+  where+    short = "Not a function"++    hints = []++    long =+        "Explanation: Expressions separated by whitespace denote function application,   \n\+        \like this:                                                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────┐                                                                     \n\+        \    │ f x │  This denotes the function ❰f❱ applied to an argument named ❰x❱     \n\+        \    └─────┘                                                                     \n\+        \                                                                                \n\+        \                                                                                \n\+        \A function is a term that has type ❰a → b❱ for some ❰a❱ or ❰b❱.  For example,   \n\+        \the following expressions are all functions because they have a function type:  \n\+        \                                                                                \n\+        \                                                                                \n\+        \                        The function's input type is ❰Bool❱                     \n\+        \                        ⇩                                                       \n\+        \    ┌───────────────────────────────┐                                           \n\+        \    │ λ(x : Bool) → x : Bool → Bool │  User-defined anonymous function          \n\+        \    └───────────────────────────────┘                                           \n\+        \                               ⇧                                                \n\+        \                               The function's output type is ❰Bool❱             \n\+        \                                                                                \n\+        \                                                                                \n\+        \                     The function's input type is ❰Natural❱                     \n\+        \                     ⇩                                                          \n\+        \    ┌───────────────────────────────┐                                           \n\+        \    │ Natural/even : Natural → Bool │  Built-in function                        \n\+        \    └───────────────────────────────┘                                           \n\+        \                               ⇧                                                \n\+        \                               The function's output type is ❰Bool❱             \n\+        \                                                                                \n\+        \                                                                                \n\+        \                        The function's input kind is ❰Type❱                     \n\+        \                        ⇩                                                       \n\+        \    ┌───────────────────────────────┐                                           \n\+        \    │ λ(a : Type) → a : Type → Type │  Type-level functions are still functions \n\+        \    └───────────────────────────────┘                                           \n\+        \                               ⇧                                                \n\+        \                               The function's output kind is ❰Type❱             \n\+        \                                                                                \n\+        \                                                                                \n\+        \             The function's input kind is ❰Type❱                                \n\+        \             ⇩                                                                  \n\+        \    ┌────────────────────┐                                                      \n\+        \    │ List : Type → Type │  Built-in type-level function                        \n\+        \    └────────────────────┘                                                      \n\+        \                    ⇧                                                           \n\+        \                    The function's output kind is ❰Type❱                        \n\+        \                                                                                \n\+        \                                                                                \n\+        \                        Function's input has kind ❰Type❱                        \n\+        \                        ⇩                                                       \n\+        \    ┌─────────────────────────────────────────────────┐                         \n\+        \    │ List/head : ∀(a : Type) → (List a → Optional a) │  A function can return  \n\+        \    └─────────────────────────────────────────────────┘  another function       \n\+        \                                ⇧                                               \n\+        \                                Function's output has type ❰List a → Optional a❱\n\+        \                                                                                \n\+        \                                                                                \n\+        \                       The function's input type is ❰List Text❱                 \n\+        \                       ⇩                                                        \n\+        \    ┌────────────────────────────────────────────┐                              \n\+        \    │ List/head Text : List Text → Optional Text │  A function applied to an    \n\+        \    └────────────────────────────────────────────┘  argument can be a function  \n\+        \                                   ⇧                                            \n\+        \                                   The function's output type is ❰Optional Text❱\n\+        \                                                                                \n\+        \                                                                                \n\+        \An expression is not a function if the expression's type is not of the form     \n\+        \❰a → b❱.  For example, these are " <> _NOT <> " functions:                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────┐                                                             \n\+        \    │ 1 : Natural │  ❰1❱ is not a function because ❰Natural❱ is not the type of \n\+        \    └─────────────┘  a function                                                 \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────┐                                                   \n\+        \    │ Natural/even 2 : Bool │  ❰Natural/even 2❱ is not a function because       \n\+        \    └───────────────────────┘  ❰Bool❱ is not the type of a function             \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────┐                                                        \n\+        \    │ List Text : Type │  ❰List Text❱ is not a function because ❰Type❱ is not   \n\+        \    └──────────────────┘  the type of a function                                \n\+        \                                                                                \n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● You tried to add two ❰Natural❱s without a space around the ❰+❱, like this:    \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────┐                                                                     \n\+        \    │ 2+2 │                                                                     \n\+        \    └─────┘                                                                     \n\+        \                                                                                \n\+        \                                                                                \n\+        \  The above code is parsed as:                                                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────┐                                                                  \n\+        \    │ 2 (+2) │                                                                  \n\+        \    └────────┘                                                                  \n\+        \      ⇧                                                                         \n\+        \      The compiler thinks that this ❰2❱ is a function whose argument is ❰+2❱    \n\+        \                                                                                \n\+        \                                                                                \n\+        \  This is because the ❰+❱ symbol has two meanings: you use ❰+❱ to add two       \n\+        \  numbers, but you also can prefix ❰Natural❱ literals with a ❰+❱ to turn them   \n\+        \  into ❰Integer❱ literals (like ❰+2❱)                                           \n\+        \                                                                                \n\+        \  To fix the code, you need to put spaces around the ❰+❱, like this:            \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────┐                                                                   \n\+        \    │ 2 + 2 │                                                                   \n\+        \    └───────┘                                                                   \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You tried to use the following expression as a function:                        \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... but this expression's type is:                                              \n\+        \                                                                                \n\+        \" <> txt1 <> "\n\+        \                                                                                \n\+        \... which is not a function type                                                \n"+      where+        txt0 = insert expr0+        txt1 = insert expr1++prettyTypeMessage (TypeMismatch expr0 expr1 expr2 expr3) = ErrorMessages {..}+  where+    short = "Wrong type of function argument\n"+        <>  "\n"+        <>  Dhall.Diff.doc (Dhall.Diff.diffNormalized expr1 expr3)++    hints = emptyRecordTypeHint expr2++    long =+        "Explanation: Every function declares what type or kind of argument to accept    \n\+        \                                                                                \n\+        \For example:                                                                    \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────────────┐                                           \n\+        \    │ λ(x : Bool) → x : Bool → Bool │  This anonymous function only accepts     \n\+        \    └───────────────────────────────┘  arguments that have type ❰Bool❱          \n\+        \                        ⇧                                                       \n\+        \                        The function's input type                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────────────┐                                           \n\+        \    │ Natural/even : Natural → Bool │  This built-in function only accepts      \n\+        \    └───────────────────────────────┘  arguments that have type ❰Natural❱       \n\+        \                     ⇧                                                          \n\+        \                     The function's input type                                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────────────┐                                           \n\+        \    │ λ(a : Type) → a : Type → Type │  This anonymous function only accepts     \n\+        \    └───────────────────────────────┘  arguments that have kind ❰Type❱          \n\+        \                        ⇧                                                       \n\+        \                        The function's input kind                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────┐                                                      \n\+        \    │ List : Type → Type │  This built-in function only accepts arguments that  \n\+        \    └────────────────────┘  have kind ❰Type❱                                    \n\+        \             ⇧                                                                  \n\+        \             The function's input kind                                          \n\+        \                                                                                \n\+        \                                                                                \n\+        \For example, the following expressions are valid:                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────┐                                                  \n\+        \    │ (λ(x : Bool) → x) True │  ❰True❱ has type ❰Bool❱, which matches the type  \n\+        \    └────────────────────────┘  of argument that the anonymous function accepts \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────┐                                                          \n\+        \    │ Natural/even 2 │  ❰2❱ has type ❰Natural❱, which matches the type of       \n\+        \    └────────────────┘  argument that the ❰Natural/even❱ function accepts,      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────┐                                                  \n\+        \    │ (λ(a : Type) → a) Bool │  ❰Bool❱ has kind ❰Type❱, which matches the kind  \n\+        \    └────────────────────────┘  of argument that the anonymous function accepts \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────┐                                                               \n\+        \    │ List Text │  ❰Text❱ has kind ❰Type❱, which matches the kind of argument   \n\+        \    └───────────┘  that that the ❰List❱ function accepts                        \n\+        \                                                                                \n\+        \                                                                                \n\+        \However, you can " <> _NOT <> " apply a function to the wrong type or kind of argument\n\+        \                                                                                \n\+        \For example, the following expressions are not valid:                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────┐                                                   \n\+        \    │ (λ(x : Bool) → x) \"A\" │  ❰\"A\"❱ has type ❰Text❱, but the anonymous function\n\+        \    └───────────────────────┘  expects an argument that has type ❰Bool❱         \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────┐                                                        \n\+        \    │ Natural/even \"A\" │  ❰\"A\"❱ has type ❰Text❱, but the ❰Natural/even❱ function\n\+        \    └──────────────────┘  expects an argument that has type ❰Natural❱           \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────┐                                                  \n\+        \    │ (λ(a : Type) → a) True │  ❰True❱ has type ❰Bool❱, but the anonymous       \n\+        \    └────────────────────────┘  function expects an argument of kind ❰Type❱     \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────┐                                                                  \n\+        \    │ List 1 │  ❰1❱ has type ❰Natural❱, but the ❰List❱ function expects an      \n\+        \    └────────┘  argument that has kind ❰Type❱                                   \n\+        \                                                                                \n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● You omit a function argument by mistake:                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────┐                                                   \n\+        \    │ List/head   [1, 2, 3] │                                                   \n\+        \    └───────────────────────┘                                                   \n\+        \                ⇧                                                               \n\+        \                ❰List/head❱ is missing the first argument,                      \n\+        \                which should be: ❰Natural❱                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \● You supply an ❰Integer❱ literal to a function that expects a ❰Natural❱        \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────┐                                                         \n\+        \    │ Natural/even +2 │                                                         \n\+        \    └─────────────────┘                                                         \n\+        \                   ⇧                                                            \n\+        \                   This should be ❰2❱                                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You tried to invoke the following function:                                     \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which expects an argument of type or kind:                                  \n\+        \                                                                                \n\+        \" <> txt1 <> "\n\+        \                                                                                \n\+        \... on the following argument:                                                  \n\+        \                                                                                \n\+        \" <> txt2 <> "\n\+        \                                                                                \n\+        \... which has a different type or kind:                                         \n\+        \                                                                                \n\+        \" <> txt3 <> "\n"+      where+        txt0 = insert expr0+        txt1 = insert expr1+        txt2 = insert expr2+        txt3 = insert expr3++prettyTypeMessage (AnnotMismatch expr0 expr1 expr2) = ErrorMessages {..}+  where+    short = "Expression doesn't match annotation\n"+        <>  "\n"+        <>  Dhall.Diff.doc (Dhall.Diff.diffNormalized expr1 expr2)++    hints = []++    long =+        "Explanation: You can annotate an expression with its type or kind using the     \n\+        \❰:❱ symbol, like this:                                                          \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────┐                                                                   \n\+        \    │ x : t │  ❰x❱ is an expression and ❰t❱ is the annotated type or kind of ❰x❱\n\+        \    └───────┘                                                                   \n\+        \                                                                                \n\+        \The type checker verifies that the expression's type or kind matches the        \n\+        \provided annotation                                                             \n\+        \                                                                                \n\+        \For example, all of the following are valid annotations that the type checker   \n\+        \accepts:                                                                        \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────┐                                                             \n\+        \    │ 1 : Natural │  ❰1❱ is an expression that has type ❰Natural❱, so the type  \n\+        \    └─────────────┘  checker accepts the annotation                             \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────┐                                                   \n\+        \    │ Natural/even 2 : Bool │  ❰Natural/even 2❱ has type ❰Bool❱, so the type    \n\+        \    └───────────────────────┘  checker accepts the annotation                   \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────┐                                                      \n\+        \    │ List : Type → Type │  ❰List❱ is an expression that has kind ❰Type → Type❱,\n\+        \    └────────────────────┘  so the type checker accepts the annotation          \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────┐                                                        \n\+        \    │ List Text : Type │  ❰List Text❱ is an expression that has kind ❰Type❱, so \n\+        \    └──────────────────┘  the type checker accepts the annotation               \n\+        \                                                                                \n\+        \                                                                                \n\+        \However, the following annotations are " <> _NOT <> " valid and the type checker will\n\+        \reject them:                                                                    \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────┐                                                                \n\+        \    │ 1 : Text │  The type checker rejects this because ❰1❱ does not have type  \n\+        \    └──────────┘  ❰Text❱                                                        \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────┐                                                             \n\+        \    │ List : Type │  ❰List❱ does not have kind ❰Type❱                           \n\+        \    └─────────────┘                                                             \n\+        \                                                                                \n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● The Haskell Dhall interpreter implicitly inserts a top-level annotation       \n\+        \  matching the expected type                                                    \n\+        \                                                                                \n\+        \  For example, if you run the following Haskell code:                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────────────┐                                           \n\+        \    │ >>> input auto \"1\" :: IO Text │                                         \n\+        \    └───────────────────────────────┘                                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \  ... then the interpreter will actually type check the following annotated     \n\+        \  expression:                                                                   \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────┐                                                                \n\+        \    │ 1 : Text │                                                                \n\+        \    └──────────┘                                                                \n\+        \                                                                                \n\+        \                                                                                \n\+        \  ... and then type-checking will fail                                          \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You or the interpreter annotated this expression:                               \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... with this type or kind:                                                     \n\+        \                                                                                \n\+        \" <> txt1 <> "\n\+        \                                                                                \n\+        \... but the inferred type or kind of the expression is actually:                \n\+        \                                                                                \n\+        \" <> txt2 <> "\n"+      where+        txt0 = insert expr0+        txt1 = insert expr1+        txt2 = insert expr2++prettyTypeMessage Untyped = ErrorMessages {..}+  where+    short = "❰Sort❱ has no type, kind, or sort"++    hints = []++    long =+        "Explanation: There are five levels of expressions that form a hierarchy:        \n\+        \                                                                                \n\+        \● terms                                                                         \n\+        \● types                                                                         \n\+        \● kinds                                                                         \n\+        \● sorts                                                                         \n\+        \● orders                                                                        \n\+        \                                                                                \n\+        \The following example illustrates this hierarchy:                               \n\+        \                                                                                \n\+        \    ┌───────────────────────────────────┐                                       \n\+        \    │ \"ABC\" : Text : Type : Kind : Sort │                                     \n\+        \    └───────────────────────────────────┘                                       \n\+        \       ⇧      ⇧      ⇧      ⇧      ⇧                                            \n\+        \       term   type   kind   sort   order                                        \n\+        \                                                                                \n\+        \There is nothing above ❰Sort❱ in this hierarchy, so if you try to type check any\n\+        \expression containing ❰Sort❱ anywhere in the expression then type checking fails\n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● You supplied a sort where a kind was expected                                 \n\+        \                                                                                \n\+        \  For example, the following expression will fail to type check:                \n\+        \                                                                                \n\+        \    ┌──────────────────┐                                                        \n\+        \    │ f : Type -> Kind │                                                        \n\+        \    └──────────────────┘                                                        \n\+        \                  ⇧                                                             \n\+        \                  ❰Kind❱ is a sort, not a kind                                  \n"++prettyTypeMessage (InvalidPredicate expr0 expr1) = ErrorMessages {..}+  where+    short = "Invalid predicate for ❰if❱: "+        <>  "\n"+        <>  Dhall.Diff.doc (Dhall.Diff.diffNormalized Bool expr1)++    hints = []++    long =+        "Explanation: Every ❰if❱ expression begins with a predicate which must have type \n\+        \❰Bool❱                                                                          \n\+        \                                                                                \n\+        \For example, these are valid ❰if❱ expressions:                                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────────┐                                            \n\+        \    │ if True then \"Yes\" else \"No\" │                                        \n\+        \    └──────────────────────────────┘                                            \n\+        \         ⇧                                                                      \n\+        \         Predicate                                                              \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────┐                                 \n\+        \    │ λ(x : Bool) → if x then False else True │                                 \n\+        \    └─────────────────────────────────────────┘                                 \n\+        \                       ⇧                                                        \n\+        \                       Predicate                                                \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but these are " <> _NOT <> " valid ❰if❱ expressions:                        \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────────┐                                               \n\+        \    │ if 0 then \"Yes\" else \"No\" │  ❰0❱ does not have type ❰Bool❱            \n\+        \    └───────────────────────────┘                                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────┐                                              \n\+        \    │ if \"\" then False else True │  ❰\"\"❱ does not have type ❰Bool❱          \n\+        \    └────────────────────────────┘                                              \n\+        \                                                                                \n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● You might be used to other programming languages that accept predicates other \n\+        \  than ❰Bool❱                                                                   \n\+        \                                                                                \n\+        \  For example, some languages permit ❰0❱ or ❰\"\"❱ as valid predicates and treat\n\+        \  them as equivalent to ❰False❱.  However, the Dhall language does not permit   \n\+        \  this                                                                          \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \Your ❰if❱ expression begins with the following predicate:                       \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... that has type:                                                              \n\+        \                                                                                \n\+        \" <> txt1 <> "\n\+        \                                                                                \n\+        \... but the predicate must instead have type ❰Bool❱                             \n"+      where+        txt0 = insert expr0+        txt1 = insert expr1++prettyTypeMessage (IfBranchMismatch expr0 expr1 expr2 expr3) =+    ErrorMessages {..}+  where+    short = "❰if❱ branches must have matching types\n"+        <>  "\n"+        <>  Dhall.Diff.doc (Dhall.Diff.diffNormalized expr1 expr3)++    hints = []++    long =+        "Explanation: Every ❰if❱ expression has a ❰then❱ and ❰else❱ branch, each of which\n\+        \is an expression:                                                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \                   Expression for ❰then❱ branch                                 \n\+        \                   ⇩                                                            \n\+        \    ┌────────────────────────────────┐                                          \n\+        \    │ if True then \"Hello, world!\"   │                                        \n\+        \    │         else \"Goodbye, world!\" │                                        \n\+        \    └────────────────────────────────┘                                          \n\+        \                   ⇧                                                            \n\+        \                   Expression for ❰else❱ branch                                 \n\+        \                                                                                \n\+        \                                                                                \n\+        \These two expressions must have the same type.  For example, the following ❰if❱ \n\+        \expressions are all valid:                                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────────────┐                                        \n\+        \    │ λ(b : Bool) → if b then 0 else 1 │ Both branches have type ❰Natural❱      \n\+        \    └──────────────────────────────────┘                                        \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────┐                                              \n\+        \    │ λ(b : Bool) →              │                                              \n\+        \    │     if b then Natural/even │ Both branches have type ❰Natural → Bool❱     \n\+        \    │          else Natural/odd  │                                              \n\+        \    └────────────────────────────┘                                              \n\+        \                                                                                \n\+        \                                                                                \n\+        \However, the following expression is " <> _NOT <> " valid:                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \                   This branch has type ❰Natural❱                               \n\+        \                   ⇩                                                            \n\+        \    ┌────────────────────────┐                                                  \n\+        \    │ if True then 0         │                                                  \n\+        \    │         else \"ABC\"     │                                                \n\+        \    └────────────────────────┘                                                  \n\+        \                   ⇧                                                            \n\+        \                   This branch has type ❰Text❱                                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \The ❰then❱ and ❰else❱ branches must have matching types, even if the predicate  \n\+        \is always ❰True❱ or ❰False❱                                                     \n\+        \                                                                                \n\+        \Your ❰if❱ expression has the following ❰then❱ branch:                           \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which has type:                                                             \n\+        \                                                                                \n\+        \" <> txt2 <> "\n\+        \                                                                                \n\+        \... and the following ❰else❱ branch:                                            \n\+        \                                                                                \n\+        \" <> txt1 <> "\n\+        \                                                                                \n\+        \... which has a different type:                                                 \n\+        \                                                                                \n\+        \" <> txt3 <> "\n\+        \                                                                                \n\+        \Fix your ❰then❱ and ❰else❱ branches to have matching types                      \n"+      where+        txt0 = insert expr0+        txt1 = insert expr1+        txt2 = insert expr2+        txt3 = insert expr3++prettyTypeMessage (ListLitInvariant) = ErrorMessages {..}+  where+    short = "Internal error: A non-empty list literal violated an internal invariant"++    hints = []++    long =+        "Explanation: Internal error: A non-empty list literal violated an internal      \n\+        \invariant.                                                                      \n\+        \                                                                                \n\+        \A non-empty list literal must always be represented as                          \n\+        \                                                                                \n\+        \    ListLit Nothing [x, y, ...]                                                 \n\+        \                                                                                \n\+        \Please file a bug report at https://github.com/dhall-lang/dhall-haskell/issues, \n\+        \ideally including the offending source code.                                    \n"++prettyTypeMessage (InvalidListType expr0) = ErrorMessages {..}+  where+    short = "Invalid type for ❰List❱"++    hints = []++    long =+        "Explanation: ❰List❱s can optionally document their type with a type annotation, \n\+        \like this:                                                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────┐                                                \n\+        \    │ [1, 2, 3] : List Natural │  A ❰List❱ of three ❰Natural❱ numbers           \n\+        \    └──────────────────────────┘                                                \n\+        \                       ⇧                                                        \n\+        \                       The type of the ❰List❱'s elements, which are ❰Natural❱   \n\+        \                       numbers                                                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────┐                                                       \n\+        \    │ [] : List Natural │  An empty ❰List❱                                      \n\+        \    └───────────────────┘                                                       \n\+        \           ⇧                                                                    \n\+        \           You must specify the type when the ❰List❱ is empty                   \n\+        \                                                                                \n\+        \                                                                                \n\+        \The type must be of the form ❰List ...❱ and not something else.  For example,   \n\+        \the following type annotation is " <> _NOT <> " valid:                          \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────┐                                                              \n\+        \    │ ... : Bool │                                                              \n\+        \    └────────────┘                                                              \n\+        \            ⇧                                                                   \n\+        \            This type does not have the form ❰List ...❱                         \n\+        \                                                                                \n\+        \                                                                                \n\+        \The element type must be a type and not something else.  For example, the       \n\+        \following element types are " <> _NOT <> " valid:                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────┐                                                            \n\+        \    │ ... : List 1 │                                                            \n\+        \    └──────────────┘                                                            \n\+        \                 ⇧                                                              \n\+        \                 This is a ❰Natural❱ number and not a ❰Type❱                    \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────┐                                                         \n\+        \    │ ... : List Type │                                                         \n\+        \    └─────────────────┘                                                         \n\+        \                 ⇧                                                              \n\+        \                 This is a ❰Kind❱ and not a ❰Type❱                              \n\+        \                                                                                \n\+        \                                                                                \n\+        \You declared that the ❰List❱ should have type:                                  \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which is not a valid list type                                              \n"+      where+        txt0 = insert expr0++prettyTypeMessage MissingListType =+    ErrorMessages {..}+  where+    short = "An empty list requires a type annotation"++    hints = []++    long =+        "Explanation: Lists do not require a type annotation if they have at least one   \n\+        \element:                                                                        \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────┐                                                               \n\+        \    │ [1, 2, 3] │  The compiler can infer that this list has type ❰List Natural❱\n\+        \    └───────────┘                                                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \However, empty lists still require a type annotation:                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────┐                                                       \n\+        \    │ [] : List Natural │  This type annotation is mandatory                    \n\+        \    └───────────────────┘                                                       \n\+        \                                                                                \n\+        \                                                                                \n\+        \You cannot supply an empty list without a type annotation                       \n"++prettyTypeMessage (MismatchedListElements i expr0 _expr1 expr2) =+    ErrorMessages {..}+  where+    short = "List elements should all have the same type\n"+        <>  "\n"+        <>  Dhall.Diff.doc (Dhall.Diff.diffNormalized expr0 expr2)++    hints = []++    long =+        "Explanation: Every element in a list must have the same type                    \n\+        \                                                                                \n\+        \For example, this is a valid ❰List❱:                                            \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────┐                                                               \n\+        \    │ [1, 2, 3] │  Every element in this ❰List❱ is a ❰Natural❱ number           \n\+        \    └───────────┘                                                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \.. but this is " <> _NOT <> " a valid ❰List❱:                                   \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────┐                                                           \n\+        \    │ [1, \"ABC\", 3] │  The first and second element have different types      \n\+        \    └───────────────┘                                                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \Your first ❰List❱ element has this type:                                        \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... but the element at index #" <> txt1 <> " has this type instead:             \n\+        \                                                                                \n\+        \" <> txt3 <> "\n"+      where+        txt0 = insert expr0+        txt1 = pretty i+        txt3 = insert expr2++prettyTypeMessage (InvalidSome expr0 expr1 expr2) = ErrorMessages {..}+  where+    short = "❰Some❱ argument has the wrong type"++    hints = []++    long =+        "Explanation: The ❰Some❱ constructor expects an argument that is a term, where   \n\+        \the type of the type of a term must be ❰Type❱                                   \n\+        \                                                                                \n\+        \For example, this is a valid use of ❰Some❱:                                     \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────┐                                                                  \n\+        \    │ Some 1 │  ❰1❱ is a valid term because ❰1 : Natural : Type❱                \n\+        \    └────────┘                                                                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but this is " <> _NOT <> " a valid ❰Optional❱ value:                        \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────┐                                                               \n\+        \    │ Some Text │  ❰Text❱ is not a valid term because ❰Text : Type : Kind ❱     \n\+        \    └───────────┘                                                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \The ❰Some❱ argument you provided:                                               \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... has this type:                                                              \n\+        \                                                                                \n\+        \" <> txt1 <> "\n\+        \                                                                                \n\+        \... but the type of that type is:                                               \n\+        \                                                                                \n\+        \" <> txt2 <> "\n\+        \                                                                                \n\+        \... which is not ❰Type❱                                                         \n"+      where+        txt0 = insert expr0+        txt1 = insert expr1+        txt2 = insert expr2++prettyTypeMessage (InvalidFieldType k expr0) = ErrorMessages {..}+  where+    short = "Invalid field type"++    hints = []++    long =+        "Explanation: Every record type annotates each field with a ❰Type❱, a ❰Kind❱, or \n\+        \a ❰Sort❱ like this:                                                             \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────────────────────────┐                            \n\+        \    │ { foo : Natural, bar : Integer, baz : Text } │  Every field is annotated  \n\+        \    └──────────────────────────────────────────────┘  with a ❰Type❱             \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────┐                                              \n\+        \    │ { foo : Type, bar : Type } │  Every field is annotated                    \n\+        \    └────────────────────────────┘  with a ❰Kind❱                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \However, the types of fields may " <> _NOT <> " be term-level values:           \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────┐                                              \n\+        \    │ { foo : Natural, bar : 1 } │  Invalid record type                         \n\+        \    └────────────────────────────┘                                              \n\+        \                             ⇧                                                  \n\+        \                             ❰1❱ is a ❰Natural❱ number and not a ❰Type❱,        \n\+        \                             ❰Kind❱, or ❰Sort❱                                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \You provided a record type with a field named:                                  \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... annotated with the following expression:                                    \n\+        \                                                                                \n\+        \" <> txt1 <> "\n\+        \                                                                                \n\+        \... which is neither a ❰Type❱, a ❰Kind❱, nor a ❰Sort❱                           \n"+      where+        txt0 = insert k+        txt1 = insert expr0++prettyTypeMessage (InvalidAlternativeType k expr0) = ErrorMessages {..}+  where+    short = "Invalid alternative type"++    hints = []++    long =+        "Explanation: Every union type specifies the type of each alternative, like this:\n\+        \                                                                                \n\+        \                                                                                \n\+        \               The type of the first alternative is ❰Bool❱                      \n\+        \               ⇩                                                                \n\+        \    ┌──────────────────────────────────┐                                        \n\+        \    │ < Left : Bool, Right : Natural > │  A union type with two alternatives    \n\+        \    └──────────────────────────────────┘                                        \n\+        \                             ⇧                                                  \n\+        \                             The type of the second alternative is ❰Natural❱    \n\+        \                                                                                \n\+        \                                                                                \n\+        \However, these alternatives can only be annotated with ❰Type❱s, ❰Kind❱s, or     \n\+        \❰Sort❱s.  For example, the following union types are " <> _NOT <> " valid:      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────┐                                              \n\+        \    │ < Left : Bool, Right : 1 > │  Invalid union type                          \n\+        \    └────────────────────────────┘                                              \n\+        \                             ⇧                                                  \n\+        \                             This is a ❰Natural❱ and not a ❰Type❱, ❰Kind❱, or   \n\+        \                             ❰Sort❱                                             \n\+        \                                                                                \n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● You accidentally typed ❰:❱ instead of ❰=❱ for a union literal with one        \n\+        \  alternative:                                                                  \n\+        \                                                                                \n\+        \    ┌─────────────────┐                                                         \n\+        \    │ < Example : 1 > │                                                         \n\+        \    └─────────────────┘                                                         \n\+        \                ⇧                                                               \n\+        \                This could be ❰=❱ instead                                       \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You provided a union type with an alternative named:                            \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... annotated with the following expression which is not a ❰Type❱, ❰Kind❱, or   \n\+        \❰Sort❱:                                                                         \n\+        \                                                                                \n\+        \" <> txt1 <> "\n"+      where+        txt0 = insert k+        txt1 = insert expr0++prettyTypeMessage (ListAppendMismatch expr0 expr1) = ErrorMessages {..}+  where+    short = "You can only append ❰List❱s with matching element types\n"+        <>  "\n"+        <>  Dhall.Diff.doc (Dhall.Diff.diffNormalized expr0 expr1)++    hints = []++    long =+        "Explanation: You can append two ❰List❱s using the ❰#❱ operator, like this:      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────┐                                                      \n\+        \    │ [1, 2, 3] # [4, 5] │                                                      \n\+        \    └────────────────────┘                                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but you cannot append two ❰List❱s if they have different element types.     \n\+        \For example, the following expression is " <> _NOT <> " valid:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \       These elements have type ❰Natural❱                                       \n\+        \       ⇩                                                                        \n\+        \    ┌───────────────────────────┐                                               \n\+        \    │ [1, 2, 3] # [True, False] │  Invalid: the element types don't match       \n\+        \    └───────────────────────────┘                                               \n\+        \                  ⇧                                                             \n\+        \                  These elements have type ❰Bool❱                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You tried to append a ❰List❱ thas has elements of type:                         \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... with another ❰List❱ that has elements of type:                              \n\+        \                                                                                \n\+        \" <> txt1 <> "\n\+        \                                                                                \n\+        \... and those two types do not match                                            \n"+      where+        txt0 = insert expr0+        txt1 = insert expr1++prettyTypeMessage (CompletionSchemaMustBeARecord expr0 expr1) = ErrorMessages {..}+  where+    short = "The completion schema must be a record"++    hints = []++    long =+        "Explanation: You can complete records using the ❰::❱ operator:                  \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────────────────────────┐ \n\+        \    │ {Type = {foo : Bool, bar : Natural}, default = {bar = 2}::{foo = True}} │ \n\+        \    └─────────────────────────────────────────────────────────────────────────┘ \n\+        \                                                                                \n\+        \... The left-hand side of :: must be a record with 'Type' and 'default' keys    \n\+        \                                                                                \n\+        \You tried to record complete the following value:                               \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which is not a record. It is:                                               \n\+        \                                                                                \n\+        \" <> txt1 <> "\n"+      where+        txt0 = insert expr0+        txt1 = insert expr1++prettyTypeMessage (InvalidRecordCompletion fieldName expr0) = ErrorMessages {..}+  where+    short = "Completion schema is missing a field: " <> pretty fieldName++    hints = []++    long =+        "Explanation: You can complete records using the ❰::❱ operator like this:\n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────────────────────────┐ \n\+        \    │ {Type = {foo : Bool, bar : Natural}, default = {bar = 2}::{foo = True}} │ \n\+        \    └─────────────────────────────────────────────────────────────────────────┘ \n\+        \                                                                                \n\+        \... but you need to have both Type and default fields in the completion schema  \n\+        \    (the record on the left of the the ::).                                     \n\+        \                                                                                \n\+        \You tried to do record completion using the schema:                             \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which is missing the key:                                                   \n\+        \                                                                                \n\+        \" <> txt1 <> "\n"+      where+        txt0 = insert expr0+        txt1 = pretty fieldName++prettyTypeMessage (MustCombineARecord c expression typeExpression) =+    ErrorMessages {..}+  where+    action = case c of+        '∧' -> "combine"+        _   -> "override"++    short = "You can only " <> action <> " records"++    hints = emptyRecordTypeHint expression++    long =+        "Explanation: You can " <> action <> " records using the ❰" <> op <> "❱ operator, like this:\n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────────────────────────┐                               \n\+        \    │ { foo = 1, bar = \"ABC\" } " <> op <> " { baz = True } │                  \n\+        \    └───────────────────────────────────────────┘                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────┐                             \n\+        \    │ λ(r : { foo : Bool }) → r " <> op <> " { bar = \"ABC\" } │                \n\+        \    └─────────────────────────────────────────────┘                             \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but you cannot " <> action <> " values that are not records.                \n\+        \                                                                                \n\+        \For example, the following expressions are " <> _NOT <> " valid:                \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────────┐                                            \n\+        \    │ { foo = 1, bar = \"ABC\" } " <> op <> " 1 │                               \n\+        \    └──────────────────────────────┘                                            \n\+        \                                 ⇧                                              \n\+        \                                 Invalid: Not a record                          \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────────────────────────┐                               \n\+        \    │ { foo = 1, bar = \"ABC\" } " <> op <> " { baz : Bool } │                  \n\+        \    └───────────────────────────────────────────┘                               \n\+        \                                 ⇧                                              \n\+        \                                 Invalid: This is a record type and not a record\n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────────────────────────┐                               \n\+        \    │ { foo = 1, bar = \"ABC\" } " <> op <> " < baz : Bool > │                  \n\+        \    └───────────────────────────────────────────┘                               \n\+        \                                 ⇧                                              \n\+        \                                 Invalid: This is a union type and not a record \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You supplied this expression as one of the arguments:                           \n\+        \                                                                                \n\+        \" <> insert expression <> "\n\+        \                                                                                \n\+        \... which is not a record, but is actually a:                                   \n\+        \                                                                                \n\+        \" <> insert typeExpression <> "\n"+      where+        op = pretty c++prettyTypeMessage (InvalidDuplicateField k expr0 expr1) =+    ErrorMessages {..}+  where+    short = "Invalid duplicate field: " <> Dhall.Pretty.Internal.prettyLabel k++    hints = []++    long =+        "Explanation: You can specify a field twice if both fields are themselves        \n\+        \records, like this:                                                             \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────────────────────────────────────┐                \n\+        \    │ { ssh = { enable = True }, ssh = { forwardX11 = True } } │                \n\+        \    └──────────────────────────────────────────────────────────┘                \n\+        \                                                                                \n\+        \                                                                                \n\+        \... because the language automatically merges two occurrences of a field using  \n\+        \the ❰∧❱ operator, and the above example is equivalent to:                       \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────┐                     \n\+        \    │ { ssh = { enable = True } ∧ { forwardX11 = True } } │                     \n\+        \    └─────────────────────────────────────────────────────┘                     \n\+        \                                                                                \n\+        \                                                                                \n\+        \... which is in turn equivalent to:                                             \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────────────────────────┐                          \n\+        \    │ { ssh = { enable = True, forwardX11 = True } } │                          \n\+        \    └────────────────────────────────────────────────┘                          \n\+        \                                                                                \n\+        \                                                                                \n\+        \However, this implies that both fields must be records since the ❰∧❱ operator   \n\+        \cannot merge non-record values.  For example, these expressions are not valid:  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────┐                                                        \n\+        \    │ { x = 0, x = 0 } │  Invalid: Neither field is a record                    \n\+        \    └──────────────────┘                                                        \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────┐                                                \n\+        \    │ { x = 0, x = { y = 0 } } │  Invalid: The first ❰x❱ field is not a record  \n\+        \    └──────────────────────────┘                                                \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You specified more than one field named:                                        \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... but one of the fields had this value:                                       \n\+        \                                                                                \n\+        \" <> txt1 <> "\n\+        \                                                                                \n\+        \... with this type:                                                             \n\+        \                                                                                \n\+        \" <> txt2 <> "\n\+        \                                                                                \n\+        \... which is not a record type                                                  \n"+      where+        txt0 = insert (Dhall.Pretty.Internal.escapeLabel AnyLabelOrSome k)+        txt1 = insert expr0+        txt2 = insert expr1++prettyTypeMessage (CombineTypesRequiresRecordType expr0 expr1) =+    ErrorMessages {..}+  where+    short = "❰⩓❱ requires arguments that are record types"++    hints = []++    long =+        "Explanation: You can only use the ❰⩓❱ operator on arguments that are record type\n\+        \literals, like this:                                                            \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────┐                                     \n\+        \    │ { age : Natural } ⩓ { name : Text } │                                     \n\+        \    └─────────────────────────────────────┘                                     \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but you cannot use the ❰⩓❱ operator on any other type of arguments.  For    \n\+        \example, you cannot use variable arguments:                                     \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────────────────┐                                       \n\+        \    │ λ(t : Type) → t ⩓ { name : Text } │  Invalid: ❰t❱ might not be a record   \n\+        \    └───────────────────────────────────┘  type                                 \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You tried to supply the following argument:                                     \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which normalized to:                                                        \n\+        \                                                                                \n\+        \" <> txt1 <> "\n\+        \                                                                                \n\+        \... which is not a record type literal                                          \n"+      where+        txt0 = insert expr0+        txt1 = insert expr1++prettyTypeMessage (DuplicateFieldCannotBeMerged ks) = ErrorMessages {..}+  where+    short = "Duplicate field cannot be merged: " <> pretty (toPath ks)++    hints = []++    long =+        "Explanation: Duplicate fields are only allowed if they are both records and if  \n\+        \the two records can be recursively merged without collisions.                   \n\+        \                                                                                \n\+        \Specifically, an expression like:                                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────┐                                                        \n\+        \    │ { x = a, x = b } │                                                        \n\+        \    └──────────────────┘                                                        \n\+        \                                                                                \n\+        \                                                                                \n\+        \... is syntactic sugar for:                                                     \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────┐                                                           \n\+        \    │ { x = a ∧ b } │                                                           \n\+        \    └───────────────┘                                                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \... which is rejected if ❰a ∧ b❱ does not type-check.  One way this can happen  \n\+        \is if ❰a❱ and ❰b❱ share a field in common that is not a record, which is known  \n\+        \as a \"collision\".                                                               \n\+        \                                                                                \n\+        \For example, the following expression is " <> _NOT <> " valid:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────────────┐                                        \n\+        \    │ { x = { y = 0 }, x = { y = 1 } } │ Invalid: The two ❰x.y❱ fields \"collide\"\n\+        \    └──────────────────────────────────┘                                        \n\+        \                                                                                \n\+        \                                                                                \n\+        \... whereas the following expression is valid:                                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────────────┐                                        \n\+        \    │ { x = { y = 0 }, x = { z = 1 } } │ Valid: the two ❰x❱ fields don't collide\n\+        \    └──────────────────────────────────┘ because they can be recursively merged \n\+        \                                                                                \n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● You specified the same field twice by mistake                                 \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You specified the following field twice:                                        \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which collided on the following path:                                       \n\+        \                                                                                \n\+        \" <> txt1 <> "\n"+      where+        txt0 = insert (Dhall.Pretty.Internal.escapeLabel AnyLabelOrSome (NonEmpty.head ks))++        txt1 = insert (toPath ks)++prettyTypeMessage (FieldCollision ks) = ErrorMessages {..}+  where+    short = "Field collision on: " <> pretty (toPath ks)++    hints = []++    long =+        "Explanation: You can recursively merge records using the ❰∧❱ operator:          \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────┐                                                   \n\+        \    │ { x = a } ∧ { y = b } │                                                   \n\+        \    └───────────────────────┘                                                   \n\+        \                                                                                \n\+        \... but two records cannot be merged in this way if they share a field that is  \n\+        \not a record.                                                                   \n\+        \                                                                                \n\+        \For example, the following expressions are " <> _NOT <> " valid:                \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────┐                                                \n\+        \    │ { x = 1 } ∧ { x = True } │  Invalid: The ❰x❱ fields \"collide\" because they\n\+        \    └──────────────────────────┘  are not records that can be merged            \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────────────┐                                        \n\+        \    │ { x = 1 } ∧ { x = { y = True } } │  Invalid: One of the two ❰x❱ fields is \n\+        \    └──────────────────────────────────┘  still not a record                    \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but the following expression is valid:                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────────────────────┐  Valid: The two ❰x❱ fields     \n\+        \    │ { x = { y = True } } ∧ { x = { z = 1 } } │  don't collide because they can\n\+        \    └──────────────────────────────────────────┘  be recursively merged         \n\+        \                                                                                \n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● You tried to use ❰∧❱ to update a field's value, like this:                    \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────────────────┐                                  \n\+        \    │ { foo = 1, bar = \"ABC\" } ∧ { foo = 2 } │                                  \n\+        \    └────────────────────────────────────────┘                                  \n\+        \                                   ⇧                                            \n\+        \                                  Invalid attempt to update ❰foo❱'s value to ❰2❱\n\+        \                                                                                \n\+        \                                                                                \n\+        \  You probably meant to use ❰⫽❱ / ❰//❱  instead:                                \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────────────────┐                                  \n\+        \    │ { foo = 1, bar = \"ABC\" } ⫽ { foo = 2 } │                                  \n\+        \    └────────────────────────────────────────┘                                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You tried to merge two records which collided on the following path:            \n\+        \                                                                                \n\+        \" <> txt0 <> "\n"+      where+        txt0 = insert (toPath ks)++prettyTypeMessage (FieldTypeCollision ks) = ErrorMessages {..}+  where+    short = "Field type collision on: " <> pretty (toPath ks)++    hints = []++    long =+        "Explanation: You can recursively merge record types using the ❰⩓❱ operator, like\n\+        \this:                                                                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────┐                                                   \n\+        \    │ { x : A } ⩓ { y : B } │                                                   \n\+        \    └───────────────────────┘                                                   \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but you cannot merge record types if two field types collide that are not   \n\+        \both record types.                                                              \n\+        \                                                                                \n\+        \For example, the following expression is " <> _NOT <> " valid:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────────┐                                          \n\+        \    │ { x : Natural } ⩓ { x : Bool } │  Invalid: The ❰x❱ fields \"collide\"       \n\+        \    └────────────────────────────────┘  because they cannot be merged           \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but the following expression is valid:                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────────────────────────┐  Valid: The ❰x❱ field    \n\+        \    │ { x : { y : Bool } } ⩓ { x : { z : Natural } } │  types don't collide and \n\+        \    └────────────────────────────────────────────────┘  can be merged           \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You tried to merge two record types which collided on the following path:       \n\+        \                                                                                \n\+        \" <> txt0 <> "\n"+      where+        txt0 = insert (toPath ks)++prettyTypeMessage (MustMergeARecord expr0 expr1) = ErrorMessages {..}+  where+    short = "❰merge❱ expects a record of handlers"++    hints = []++    long =+        "Explanation: You can ❰merge❱ the alternatives of a union or an ❰Optional❱ using \n\+        \a record with one handler per alternative, like this:                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────────────────────┐     \n\+        \    │     let union    = < Left : Natural | Right : Bool >.Left 2         │     \n\+        \    │ in  let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │     \n\+        \    │ in  merge handlers union                                            │     \n\+        \    └─────────────────────────────────────────────────────────────────────┘     \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but the first argument to ❰merge❱ must be a record and not some other type. \n\+        \                                                                                \n\+        \For example, the following expression is " <> _NOT <> " valid:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────┐                             \n\+        \    │ let handler = λ(x : Bool) → x               │                             \n\+        \    │ in  merge handler (< Foo : Bool >.Foo True) │                             \n\+        \    └─────────────────────────────────────────────┘                             \n\+        \                ⇧                                                               \n\+        \                Invalid: ❰handler❱ isn't a record                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● You accidentally provide an empty record type instead of an empty record when \n\+        \  you ❰merge❱ an empty union:                                                   \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────────────────────┐                                \n\+        \    │ λ(x : <>) → λ(a : Type) → merge {} x : a │                                \n\+        \    └──────────────────────────────────────────┘                                \n\+        \                                      ⇧                                         \n\+        \                                      This should be ❰{=}❱ instead              \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You provided the following handler:                                             \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which is not a record, but is actually a value of type:                     \n\+        \                                                                                \n\+        \" <> txt1 <> "\n"+      where+        txt0 = insert expr0+        txt1 = insert expr1++prettyTypeMessage (MustMergeUnionOrOptional expr0 expr1) = ErrorMessages {..}+  where+    short = "❰merge❱ expects a union or an ❰Optional❱"++    hints = []++    long =+        "Explanation: You can ❰merge❱ the alternatives of a union or an ❰Optional❱ using \n\+        \a record with one handler per alternative, like this:                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────────────────┐         \n\+        \    │ let union    = < Left : Natural | Right : Bool >.Left 2         │         \n\+        \    │ let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │         \n\+        \    │ in  merge handlers union                                        │         \n\+        \    └─────────────────────────────────────────────────────────────────┘         \n\+        \                                                                                \n\+        \                                                                                \n\+        \... or this:                                                                    \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────────┐                 \n\+        \    │ let optional = None Bool                                │                 \n\+        \    │ let handlers = { None = False, Some = λ(x : Bool) → x } │                 \n\+        \    │ in  merge handlers optional                             │                 \n\+        \    └─────────────────────────────────────────────────────────┘                 \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but the second argument to ❰merge❱ must not be some other type.             \n\+        \                                                                                \n\+        \For example, the following expression is " <> _NOT <> " valid:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────────────────────┐                                \n\+        \    │ let handlers = { Foo = λ(x : Bool) → x } │                                \n\+        \    │ in  merge handlers True                  │                                \n\+        \    └──────────────────────────────────────────┘                                \n\+        \                         ⇧                                                      \n\+        \                         Invalid: ❰True❱ isn't a union or an ❰Optional❱         \n\+        \                                                                                \n\+        \                                                                                \n\+        \You tried to ❰merge❱ this expression:                                           \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which is not a union or an ❰Optional❱, but is actually a value of type:     \n\+        \                                                                                \n\+        \" <> txt1 <> "\n"+      where+        txt0 = insert expr0+        txt1 = insert expr1++prettyTypeMessage (UnusedHandler ks) = ErrorMessages {..}+  where+    short = "Unused handler"++    hints = []++    long =+        "Explanation: You can ❰merge❱ the alternatives of a union or an ❰Optional❱ using \n\+        \a record with one handler per alternative, like this:                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────────────────┐         \n\+        \    │ let union    = < Left : Natural | Right : Bool >.Left 2         │         \n\+        \    │ let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │         \n\+        \    │ in  merge handlers union                                        │         \n\+        \    └─────────────────────────────────────────────────────────────────┘         \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but you must provide exactly one handler per alternative in the union.  You \n\+        \cannot supply extra handlers                                                    \n\+        \                                                                                \n\+        \For example, the following expression is " <> _NOT <> " valid:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────────────────────┐                                \n\+        \    │ let union    = < Left : Natural >.Left 2 │  The ❰Right❱ alternative is    \n\+        \    │ let handlers =                           │  missing                       \n\+        \    │             { Left  = Natural/even       │                                \n\+        \    │             , Right = λ(x : Bool) → x    │  Invalid: ❰Right❱ handler isn't\n\+        \    │             }                            │           used                 \n\+        \    │ in  merge handlers union                 │                                \n\+        \    └──────────────────────────────────────────┘                                \n\+        \                                                                                \n\+        \                                                                                \n\+        \You provided the following handlers:                                            \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which had no matching alternatives in the union you tried to ❰merge❱        \n"+      where+        txt0 = insert (Text.intercalate ", " (Data.Set.toList ks))++prettyTypeMessage (MissingHandler exemplar ks) = ErrorMessages {..}+  where+    short = case Data.Set.toList ks of+         []       -> "Missing handler: " <> Dhall.Pretty.Internal.prettyLabel exemplar+         xs@(_:_) -> "Missing handlers: " <> (Pretty.hsep . Pretty.punctuate Pretty.comma+                                             . map Dhall.Pretty.Internal.prettyLabel $ exemplar:xs)++    hints = []++    long =+        "Explanation: You can ❰merge❱ the alternatives of a union or an ❰Optional❱ using \n\+        \a record with one handler per alternative, like this:                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────────────────┐         \n\+        \    │ let union    = < Left : Natural | Right : Bool >.Left 2         │         \n\+        \    │ let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │         \n\+        \    │ in  merge handlers union                                        │         \n\+        \    └─────────────────────────────────────────────────────────────────┘         \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but you must provide exactly one handler per alternative in the union.  You \n\+        \cannot omit any handlers                                                        \n\+        \                                                                                \n\+        \For example, the following expression is " <> _NOT <> " valid:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \                                          Invalid: Missing ❰Right❱ handler      \n\+        \                                          ⇩                                     \n\+        \    ┌──────────────────────────────────────────────────────────────┐            \n\+        \    │ let handlers = { Left = Natural/even }                       │            \n\+        \    │ let union    = < Left : Natural | Right : Bool >.Left 2      │            \n\+        \    │ in  merge handlers union                                     │            \n\+        \    └──────────────────────────────────────────────────────────────┘            \n\+        \                                                                                \n\+        \                                                                                \n\+        \Note that you need to provide handlers for other alternatives even if those     \n\+        \alternatives are never used                                                     \n\+        \                                                                                \n\+        \You need to supply the following handlers:                                      \n\+        \                                                                                \n\+        \" <> txt0 <> "\n"+      where+        txt0 = insert (Text.intercalate ", " (exemplar : Data.Set.toList ks))++prettyTypeMessage MissingMergeType =+    ErrorMessages {..}+  where+    short = "An empty ❰merge❱ requires a type annotation"++    hints = []++    long =+        "Explanation: A ❰merge❱ does not require a type annotation if the union has at   \n\+        \least one alternative, like this                                                \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────────────────┐         \n\+        \    │ let union    = < Left : Natural | Right : Bool >.Left 2         │         \n\+        \    │ let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │         \n\+        \    │ in  merge handlers union                                        │         \n\+        \    └─────────────────────────────────────────────────────────────────┘         \n\+        \                                                                                \n\+        \                                                                                \n\+        \However, you must provide a type annotation when merging an empty union:        \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────────┐                                          \n\+        \    │ λ(a : <>) → merge {=} a : Bool │                                          \n\+        \    └────────────────────────────────┘                                          \n\+        \                                ⇧                                               \n\+        \                                This can be any type                            \n\+        \                                                                                \n\+        \                                                                                \n\+        \You can provide any type at all as the annotation, since merging an empty       \n\+        \union can produce any type of output                                            \n"++prettyTypeMessage (HandlerInputTypeMismatch expr0 expr1 expr2) =+    ErrorMessages {..}+  where+    short = "Wrong handler input type\n"+        <>  "\n"+        <>  Dhall.Diff.doc (Dhall.Diff.diffNormalized expr1 expr2)++    hints = []++    long =+        "Explanation: You can ❰merge❱ the alternatives of a union or an ❰Optional❱ using \n\+        \a record with one handler per alternative, like this:                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────────────────┐         \n\+        \    │ let union    = < Left : Natural | Right : Bool >.Left 2         │         \n\+        \    │ let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │         \n\+        \    │ in  merge handlers union                                        │         \n\+        \    └─────────────────────────────────────────────────────────────────┘         \n\+        \                                                                                \n\+        \                                                                                \n\+        \... as long as the input type of each handler function matches the type of the  \n\+        \corresponding alternative:                                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────────────────────────────────────────┐               \n\+        \    │ union    : < Left : Natural       | Right : Bool        > │               \n\+        \    └───────────────────────────────────────────────────────────┘               \n\+        \                          ⇧                       ⇧                             \n\+        \                   These must match        These must match                     \n\+        \                          ⇩                       ⇩                             \n\+        \    ┌───────────────────────────────────────────────────────────┐               \n\+        \    │ handlers : { Left : Natural → Bool, Right : Bool → Bool } │               \n\+        \    └───────────────────────────────────────────────────────────┘               \n\+        \                                                                                \n\+        \                                                                                \n\+        \For example, the following expression is " <> _NOT <> " valid:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \      Invalid: Doesn't match the type of the ❰Right❱ alternative                \n\+        \                                                               ⇩                \n\+        \    ┌──────────────────────────────────────────────────────────────────┐        \n\+        \    │ let handlers = { Left = Natural/even | Right = λ(x : Text) → x } │        \n\+        \    │ let union    = < Left : Natural | Right : Bool >.Left 2          │        \n\+        \    │ in  merge handlers union                                         │        \n\+        \    └──────────────────────────────────────────────────────────────────┘        \n\+        \                                                                                \n\+        \                                                                                \n\+        \Your handler for the following alternative:                                     \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... needs to accept an input value of type:                                     \n\+        \                                                                                \n\+        \" <> txt1 <> "\n\+        \                                                                                \n\+        \... but actually accepts an input value of a different type:                    \n\+        \                                                                                \n\+        \" <> txt2 <> "\n"+      where+        txt0 = insert expr0+        txt1 = insert expr1+        txt2 = insert expr2++prettyTypeMessage (DisallowedHandlerType label handlerType handlerOutputType variable) =+    ErrorMessages {..}+  where+    short = "Disallowed handler type"++    hints = []++    long =+        "Explanation: You can ❰merge❱ the alternatives of a union or an ❰Optional❱ using \n\+        \a record with one handler per alternative, like this:                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────────────────┐         \n\+        \    │ let union    = < Left : Natural | Right : Bool >.Left 2         │         \n\+        \    │ let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │         \n\+        \    │ in  merge handlers union                                        │         \n\+        \    └─────────────────────────────────────────────────────────────────┘         \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but the output type of a handler may not depend on the input value.         \n\+        \                                                                                \n\+        \For example, the following expression is " <> _NOT <> " valid:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \      Invalid: The output type is ❰Optional A❱, which references the input      \n\+        \      value ❰A❱.                                                                \n\+        \                  ⇩                                                             \n\+        \    ┌──────────────────────────────────────────┐                                \n\+        \    │ merge { x = None } (< x : Type >.x Bool) │                                \n\+        \    └──────────────────────────────────────────┘                                \n\+        \                                                                                \n\+        \                                                                                \n\+        \Your handler for the following alternative:                                     \n\+        \                                                                                \n\+        \" <> insert label <> "\n\+        \                                                                                \n\+        \... has type:                                                                   \n\+        \                                                                                \n\+        \" <> insert handlerType <> "\n\+        \                                                                                \n\+        \... where the output type:                                                      \n\+        \                                                                                \n\+        \" <> insert handlerOutputType <> "\n\+        \                                                                                \n\+        \... references the handler's input value:                                       \n\+        \                                                                                \n\+        \" <> insert variable <> "\n"++prettyTypeMessage (HandlerOutputTypeMismatch key0 expr0 key1 expr1) =+    ErrorMessages {..}+  where+    short = "Handlers should have the same output type\n"+        <>  "\n"+        <>  Dhall.Diff.doc (Dhall.Diff.diffNormalized expr0 expr1)++    hints = []++    long =+        "Explanation: You can ❰merge❱ the alternatives of a union or an ❰Optional❱ using \n\+        \a record with one handler per alternative, like this:                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────────────────┐         \n\+        \    │ let union    = < Left : Natural | Right : Bool >.Left 2         │         \n\+        \    │ let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │         \n\+        \    │ in  merge handlers union                                        │         \n\+        \    └─────────────────────────────────────────────────────────────────┘         \n\+        \                                                                                \n\+        \                                                                                \n\+        \... as long as the output type of each handler function is the same:            \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────────────────────────────────────────┐               \n\+        \    │ handlers : { Left : Natural → Bool, Right : Bool → Bool } │               \n\+        \    └───────────────────────────────────────────────────────────┘               \n\+        \                                    ⇧                    ⇧                      \n\+        \                                These output types both match                   \n\+        \                                                                                \n\+        \                                                                                \n\+        \For example, the following expression is " <> _NOT <> " valid:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────┐                         \n\+        \    │ let Union = < Left : Natural | Right : Bool >   │                         \n\+        \    │ let handlers =                                  │                         \n\+        \    │              { Left  = λ(x : Natural) → x       │  This outputs ❰Natural❱ \n\+        \    │              , Right = λ(x : Bool   ) → x       │  This outputs ❰Bool❱    \n\+        \    │              }                                  │                         \n\+        \    │ in  merge handlers (Union.Left 2)               │                         \n\+        \    └─────────────────────────────────────────────────┘                         \n\+        \                ⇧                                                               \n\+        \                Invalid: The handlers in this record don't have matching outputs\n\+        \                                                                                \n\+        \                                                                                \n\+        \The handler for the ❰" <> txt0 <> "❱ alternative has this output type:          \n\+        \                                                                                \n\+        \" <> txt1 <> "\n\+        \                                                                                \n\+        \... but the handler for the ❰" <> txt2 <> "❱ alternative has this output type instead:\n\+        \                                                                                \n\+        \" <> txt3 <> "\n"+      where+        txt0 = pretty key0+        txt1 = insert expr0+        txt2 = pretty key1+        txt3 = insert expr1++prettyTypeMessage (HandlerNotAFunction k expr0) = ErrorMessages {..}+  where+    short = "Handler for "<> Dhall.Pretty.Internal.prettyLabel k <> " is not a function"++    hints = []++    long =+        "Explanation: You can ❰merge❱ the alternatives of a union or an ❰Optional❱ using \n\+        \a record with one handler per alternative, like this:                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────────────────┐         \n\+        \    │ let union    = < Left : Natural | Right : Bool >.Left 2         │         \n\+        \    │ let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │         \n\+        \    │ in  merge handlers union                                        │         \n\+        \    └─────────────────────────────────────────────────────────────────┘         \n\+        \                                                                                \n\+        \                                                                                \n\+        \... as long as each handler is a function -- FIXME                              \n\+        \                                                                                \n\+        \For example, the following expression is " <> _NOT <> " valid:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────────────────────────┐                          \n\+        \    │ merge { Foo = True } (< Foo : Natural >.Foo 1) │                          \n\+        \    └────────────────────────────────────────────────┘                          \n\+        \                    ⇧                                                           \n\+        \                    Invalid: Not a function                                     \n\+        \                                                                                \n\+        \                                                                                \n\+        \Your handler for this alternative:                                              \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... has the following type:                                                     \n\+        \                                                                                \n\+        \" <> txt1 <> "\n\+        \                                                                                \n\+        \... which is not the type of a function                                         \n"+      where+        txt0 = insert k+        txt1 = insert expr0++prettyTypeMessage (MustMapARecord provided _providedType) = ErrorMessages {..}+  where+    short = "❰toMap❱ expects a record value"++    hints = emptyRecordTypeHint provided++    long =+        "Explanation: You can apply ❰toMap❱ to any homogenous record, like this:         \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────────────────────┐     \n\+        \    │ let record = { one = 1, two = 2 }                                   │     \n\+        \    │ in  toMap record : List { mapKey : Text, mapValue : Natural}        │     \n\+        \    └─────────────────────────────────────────────────────────────────────┘     \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but the argument to ❰toMap❱ must be a record and not some other type.       \n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● You accidentally provide an empty record type instead of an empty record when \n\+        \  using ❰toMap❱:                                                                \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────────────────────────────────────┐                   \n\+        \    │ toMap {} : List { mapKey : Text, mapValue : Natural } │                   \n\+        \    └───────────────────────────────────────────────────────┘                   \n\+        \            ⇧                                                                   \n\+        \            This should be ❰{=}❱ instead                                        \n"++prettyTypeMessage (InvalidToMapRecordKind type_ kind) = ErrorMessages {..}+  where+    short = "❰toMap❱ expects a record of kind ❰Type❱"++    hints = []++    long =+        "Explanation: You can apply ❰toMap❱ to any homogenous record of kind ❰Type❱, like\n\+        \ this:                                                                          \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────────────────────┐     \n\+        \    │ let record = { one = 1, two = 2 }                                   │     \n\+        \    │ in  toMap record : List { mapKey : Text, mapValue : Natural}        │     \n\+        \    └─────────────────────────────────────────────────────────────────────┘     \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but records of kind ❰Kind❱ or ❰Sort❱ cannot be turned into ❰List❱s.         \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You applied ❰toMap❱ to a record of the following type:                          \n\+        \                                                                                \n\+        \" <> insert type_ <> "\n\+        \                                                                                \n\+        \... which has kind                                                              \n\+        \                                                                                \n\+        \" <> insert kind <> "\n"++prettyTypeMessage (HeterogenousRecordToMap _expr0 _expr1 _expr2) = ErrorMessages {..}+  where+    short = "❰toMap❱ expects a homogenous record"++    hints = []++    long =+        "Explanation: You can apply ❰toMap❱ to any homogenous record, like this:         \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────────────────────┐     \n\+        \    │ let record = { one = 1, two = 2 }                                   │     \n\+        \    │ in  toMap record : List { mapKey : Text, mapValue : Natural}        │     \n\+        \    └─────────────────────────────────────────────────────────────────────┘     \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but every field of the record must have the same type.                      \n\+        \                                                                                \n\+        \For example, the following expression is " <> _NOT <> " valid:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────┐                                 \n\+        \    │ toMap { Foo = True, Bar = 0 }           │                                 \n\+        \    └─────────────────────────────────────────┘                                 \n\+        \                    ⇧           ⇧                                               \n\+        \                    Bool        Natural                                         \n"++prettyTypeMessage (MapTypeMismatch expr0 expr1) = ErrorMessages {..}+  where+    short = "❰toMap❱ result type doesn't match annotation"+        <>  "\n"+        <>  Dhall.Diff.doc (Dhall.Diff.diffNormalized expr0 expr1)++    hints = []++    long =+        "Explanation: a ❰toMap❱ application has been annotated with a type that doesn't  \n\+        \match its inferred type.                                                        \n"++prettyTypeMessage (InvalidToMapType expr) =+    ErrorMessages {..}+  where+    short = "An empty ❰toMap❱ was annotated with an invalid type"+        <>  "\n"+        <>  insert expr++    hints = []++    long =+        "Explanation: A ❰toMap❱ applied to an empty record must have a type annotation:  \n\+        \that matches a list of key-value pairs, like this                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────────────────────┐     \n\+        \    │ toMap {=} : List { mapKey : Text, mapValue : Natural}               │     \n\+        \    └─────────────────────────────────────────────────────────────────────┘     \n\+        \                                                                                \n\+        \The type you have provided doesn't match the expected form.                     \n\+        \                                                                                \n"++prettyTypeMessage MissingToMapType =+    ErrorMessages {..}+  where+    short = "An empty ❰toMap❱ requires a type annotation"++    hints = []++    long =+        "Explanation: A ❰toMap❱ does not require a type annotation if the record has at  \n\+        \least one field, like this                                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────────────────────┐     \n\+        \    │ let record = { one = 1, two = 2 }                                   │     \n\+        \    │ in  toMap record                                                    │     \n\+        \    └─────────────────────────────────────────────────────────────────────┘     \n\+        \                                                                                \n\+        \                                                                                \n\+        \However, you must provide a type annotation with an empty record:               \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────────────────────┐     \n\+        \    │ toMap {=} : List { mapKey : Text, mapValue : Natural}               │     \n\+        \    └─────────────────────────────────────────────────────────────────────┘     \n\+        \                                                                                \n"++prettyTypeMessage (CantAccess lazyText0 expr0 expr1) = ErrorMessages {..}+  where+    short = "Not a record or a union"++    hints = []++    long =+        "Explanation: You can only access fields on records or unions, like this:        \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────┐                                         \n\+        \    │ { foo = True, bar = \"ABC\" }.foo │  This is valid ...                    \n\+        \    └─────────────────────────────────┘                                         \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────────────────────────┐                               \n\+        \    │ λ(r : { foo : Bool, bar : Text }) → r.foo │  ... and so is this           \n\+        \    └───────────────────────────────────────────┘                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────┐                                         \n\+        \    │ < foo : Bool | bar : Text >.foo │  ... and so is this                     \n\+        \    └─────────────────────────────────┘                                         \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────────────────────┐                              \n\+        \    │ λ(r : < foo : Bool | bar : Text >) → r.foo │  ... and so is this          \n\+        \    └────────────────────────────────────────────┘                              \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but you cannot access fields on non-record expressions                      \n\+        \                                                                                \n\+        \For example, the following expression is " <> _NOT <> " valid:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────┐                                                                   \n\+        \    │ 1.foo │                                                                   \n\+        \    └───────┘                                                                   \n\+        \      ⇧                                                                         \n\+        \      Invalid: Not a record                                                     \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You tried to access the field:                                                  \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... on the following expression which is not a record nor a union type:         \n\+        \                                                                                \n\+        \" <> txt1 <> "\n\+        \                                                                                \n\+        \... but is actually an expression of type:                                      \n\+        \                                                                                \n\+        \" <> txt2 <> "\n"+      where+        txt0 = insert lazyText0+        txt1 = insert expr0+        txt2 = insert expr1++prettyTypeMessage (CantProject lazyText0 expr0 expr1) = ErrorMessages {..}+  where+    short = "Not a record"++    hints = []++    long =+        "Explanation: You can only project fields on records, like this:                 \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────────────┐                     \n\+        \    │ { foo = True, bar = \"ABC\", baz = 1 }.{ foo, bar } │  This is valid ...  \n\+        \    └─────────────────────────────────────────────────────┘                     \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────────────────────────────────────────────┐      \n\+        \    │ λ(r : { foo : Bool, bar : Text , baz : Natural }) → r.{ foo, bar } │  ... and so is this           \n\+        \    └────────────────────────────────────────────────────────────────────┘      \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but you cannot project fields on non-record expressions                     \n\+        \                                                                                \n\+        \For example, the following expression is " <> _NOT <> " valid:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────┐                                                          \n\+        \    │ 1.{ foo, bar } │                                                          \n\+        \    └────────────────┘                                                          \n\+        \      ⇧                                                                         \n\+        \      Invalid: Not a record                                                     \n\+        \                                                                                \n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● You accidentally try to project fields of a union instead of a record, like   \n\+        \  this:                                                                         \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────────────┐                                      \n\+        \    │ < foo : a | bar : b >.{ foo, bar } │                                      \n\+        \    └────────────────────────────────────┘                                      \n\+        \      ⇧                                                                         \n\+        \      This is a union, not a record                                             \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You tried to access the fields:                                                 \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... on the following expression which is not a record:                          \n\+        \                                                                                \n\+        \" <> txt1 <> "\n\+        \                                                                                \n\+        \... but is actually an expression of type:                                      \n\+        \                                                                                \n\+        \" <> txt2 <> "\n"+      where+        txt0 = insert lazyText0+        txt1 = insert expr0+        txt2 = insert expr1++prettyTypeMessage (CantProjectByExpression expr) = ErrorMessages {..}+  where+    short = "Selector is not a record type"++    hints = []++    long =+        "Explanation: You can project by an expression if that expression is a record    \n\+        \type:                                                                           \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────┐                                         \n\+        \    │ { foo = True }.({ foo : Bool }) │  This is valid ...                      \n\+        \    └─────────────────────────────────┘                                         \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────────────────────┐                                \n\+        \    │ λ(r : { foo : Bool }) → r.{ foo : Bool } │  ... and so is this            \n\+        \    └──────────────────────────────────────────┘                                \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but you cannot project by any other type of expression:                     \n\+        \                                                                                \n\+        \For example, the following expression is " <> _NOT <> " valid:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────┐                                                   \n\+        \    │ { foo = True }.(True) │                                                   \n\+        \    └───────────────────────┘                                                   \n\+        \                      ⇧                                                         \n\+        \                      Invalid: Not a record type                                \n\+        \                                                                                \n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● You accidentally try to project by a record value instead of a record type,   \n\+        \  like this:                                                                    \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────┐                                         \n\+        \    │ let T = { foo : Bool }          │                                         \n\+        \    │                                 │                                         \n\+        \    │ let x = { foo = True , bar = 1} │                                         \n\+        \    │                                 │                                         \n\+        \    │ let y = { foo = False, bar = 2} │                                         \n\+        \    │                                 │                                         \n\+        \    │ in  x.(y)                       │                                         \n\+        \    └─────────────────────────────────┘                                         \n\+        \             ⇧                                                                  \n\+        \             The user might have meant ❰T❱ here                                 \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You tried to project out the following type:                                    \n\+        \                                                                                \n\+        \" <> txt <> "\n\+        \                                                                                \n\+        \... which is not a record type                                                  \n"+      where+        txt = insert expr++prettyTypeMessage (DuplicateProjectionLabel k) = ErrorMessages {..}+  where+    short = "Duplicate projection label: " <> Dhall.Pretty.Internal.prettyLabel k++    hints = []++    long =+        "Explanation: You can only specify a label once when projecting a record's fields\n\+        \by label.  For example, this is valid:                                          \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────┐                                 \n\+        \    │ { x = 1.1, y = 2.4, z = -0.3 }.{ x, y } │                                 \n\+        \    └─────────────────────────────────────────┘                                 \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but this is not valid:                                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────┐                                 \n\+        \    │ { x = 1.1, y = 2.4, z = -0.3 }.{ y, y } │                                 \n\+        \    └─────────────────────────────────────────┘                                 \n\+        \                                          ⇧                                     \n\+        \                                          Invalid: the label ❰y❱ appears twice  \n\+        \                                                                                \n\+        \                                                                                \n\+        \You tried to project the following field twice:                                 \n\+        \                                                                                \n\+        \" <> txt0 <> "\n"+      where+        txt0 = insert k++prettyTypeMessage (MissingField k expr0) = ErrorMessages {..}+  where+    short = "Missing record field: " <> Dhall.Pretty.Internal.prettyLabel k++    hints = []++    long =+        "Explanation: You can only access fields on records, like this:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────┐                                         \n\+        \    │ { foo = True, bar = \"ABC\" }.foo │  This is valid ...                    \n\+        \    └─────────────────────────────────┘                                         \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────────────────────────┐                               \n\+        \    │ λ(r : { foo : Bool, bar : Text }) → r.foo │  ... and so is this           \n\+        \    └───────────────────────────────────────────┘                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but you can only access fields if they are present                          \n\+        \                                                                                \n\+        \For example, the following expression is " <> _NOT <> " valid:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────┐                                         \n\+        \    │ { foo = True, bar = \"ABC\" }.qux │                                       \n\+        \    └─────────────────────────────────┘                                         \n\+        \                                  ⇧                                             \n\+        \                                  Invalid: the record has no ❰qux❱ field        \n\+        \                                                                                \n\+        \                                                                                \n\+        \You tried to access a field named:                                              \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... but the field is missing because the record only defines the following      \n\+        \fields:                                                                         \n\+        \                                                                                \n\+        \" <> txt1 <> "\n"+      where+        txt0 = insert k+        txt1 = insert expr0++prettyTypeMessage (MissingConstructor k expr0) = ErrorMessages {..}+  where+    short = "Missing constructor: " <> Dhall.Pretty.Internal.prettyLabel k++    hints = []++    long =+        "Explanation: You can access constructors from unions, like this:                \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────┐                                                       \n\+        \    │ < Foo | Bar >.Foo │  This is valid ...                                    \n\+        \    └───────────────────┘                                                       \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but you can only access constructors if they match an union alternative of  \n\+        \the same name.                                                                  \n\+        \                                                                                \n\+        \For example, the following expression is " <> _NOT <> " valid:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────┐                                                       \n\+        \    │ < Foo | Bar >.Baz │                                                       \n\+        \    └───────────────────┘                                                       \n\+        \                    ⇧                                                           \n\+        \                    Invalid: the union has no ❰Baz❱ alternative                 \n\+        \                                                                                \n\+        \                                                                                \n\+        \You tried to access a constructor named:                                        \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... but the constructor is missing because the union only defines the following \n\+        \alternatives:                                                                   \n\+        \                                                                                \n\+        \" <> txt1 <> "\n"+      where+        txt0 = insert k+        txt1 = insert expr0++prettyTypeMessage (ProjectionTypeMismatch k expr0 expr1 expr2 expr3) = ErrorMessages {..}+  where+    short = "Projection type mismatch\n"+        <>  "\n"+        <>  Dhall.Diff.doc (Dhall.Diff.diffNormalized expr2 expr3)++    hints = []++    long =+        "Explanation: You can project a subset of fields from a record by specifying the \n\+        \desired type of the final record, like this:                                    \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────────┐                             \n\+        \    │ { foo = 1, bar = True }.({ foo : Natural }) │  This is valid              \n\+        \    └─────────────────────────────────────────────┘                             \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but the expected type for each desired field must match the actual type of  \n\+        \the corresponding field in the original record.                                 \n\+        \                                                                                \n\+        \For example, the following expression is " <> _NOT <> " valid:                  \n\+        \                                                                                \n\+        \              Invalid: The ❰foo❱ field contains ❰1❱, which has type ❰Natural❱...\n\+        \              ⇩                                                                 \n\+        \    ┌──────────────────────────────────────────┐                                \n\+        \    │ { foo = 1, bar = True }.({ foo : Text }) │                                \n\+        \    └──────────────────────────────────────────┘                                \n\+        \                                       ⇧                                        \n\+        \                                       ... but we requested that the ❰foo❱ field\n\+        \                                       must contain a value of type ❰Text❱      \n\+        \                                                                                \n\+        \                                                                                \n\+        \You tried to project out a field named:                                         \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... that should have type:                                                      \n\+        \                                                                                \n\+        \" <> txt1 <> "\n\+        \                                                                                \n\+        \... but that field instead had a value of type:                                 \n\+        \                                                                                \n\+        \" <> txt2 <> "\n"+      where+        txt0 = insert k+        txt1 = insert expr0+        txt2 = insert expr1++prettyTypeMessage (AssertionFailed expr0 expr1) = ErrorMessages {..}+  where+    short = "Assertion failed\n"+        <>  "\n"+        <>  Dhall.Diff.doc (Dhall.Diff.diffNormalized expr0 expr1)++    hints = []++    long =+        "Explanation: You can assert at type-checking time that two terms are equal if   \n\+        \they have the same normal form, like this:                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────┐                                                      \n\+        \    │ assert : 2 + 2 ≡ 4 │  This is valid                                       \n\+        \    └────────────────────┘                                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \... and an assertion still succeeds if the normal forms only differ by renaming \n\+        \bound variables, like this:                                                     \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────────────────────────────────┐                    \n\+        \    │ assert : λ(n : Natural) → n + 0 ≡ λ(m : Natural) → m │  This is also valid\n\+        \    └──────────────────────────────────────────────────────┘                    \n\+        \                                                                                \n\+        \                                                                                \n\+        \However, an assertion fails if the normal forms differ in any other way.  For   \n\+        \example, the following assertion is " <> _NOT <> " valid:                       \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────┐                                                          \n\+        \    │ assert : 0 ≡ 1 │  Invalid: ❰0❱ does not equal ❰1❱                         \n\+        \    └────────────────┘                                                          \n\+        \                                                                                \n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● You might have tried to ❰assert❱ a precondition on a function's input, like   \n\+        \  this:                                                                         \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────────────────────────────────────────────┐        \n\+        \    │ λ(n : Natural) → let _ = assert : Natural/isZero n ≡ False in n  │        \n\+        \    └──────────────────────────────────────────────────────────────────┘        \n\+        \                                        ⇧                                       \n\+        \                                        Invalid: This assertion will always fail\n\+        \                                                                                \n\+        \                                                                                \n\+        \  This will not work.  Such an assertion is checking all possible inputs to the \n\+        \  function, before you've even used the function at all.                        \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You tried to assert that this expression:                                       \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... is the same as this other expression:                                       \n\+        \                                                                                \n\+        \" <> txt1 <> "\n\+        \                                                                                \n\+        \... but they differ\n"+      where+        txt0 = insert expr0+        txt1 = insert expr1++prettyTypeMessage (NotAnEquivalence expr) = ErrorMessages {..}+  where+    short = "Not an equivalence\n"++    hints = []++    long =+        "Explanation: The type annotation for an ❰assert❱ must evaluate to an equivalence\n\+        \of the form ❰x ≡ y❱, like this:                                                 \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────┐                                                      \n\+        \    │ assert : 2 + 2 ≡ 4 │  This is valid                                       \n\+        \    └────────────────────┘                                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but any other type is not a valid annotation.  For example, the following   \n\+        \assertion is " <> _NOT <> " valid:                                              \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────┐                                                           \n\+        \    │ assert : True │  Invalid: ❰True❱ is not an equivalence                    \n\+        \    └───────────────┘                                                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● You tried to supply an expression of type ❰Bool❱ to the assertion, rather than\n\+        \  two separate expressions to compare, like this:                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────────┐                                               \n\+        \    │ assert : Natural/isZero 0 │  Invalid: A boolean expression is not the     \n\+        \    └───────────────────────────┘  same thing as a type-level equivalence       \n\+        \                                                                                \n\+        \                                                                                \n\+        \  You have to explicitly compare two expressions, even if that just means       \n\+        \  comparing the expression to ❰True❱, like this:                                \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────────────┐                                        \n\+        \    │ assert : Natural/isZero 0 ≡ True │  Valid: You can assert that two boolean\n\+        \    └──────────────────────────────────┘  expressions are equivalent            \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You provided the following type annotation for an ❰assert❱:                     \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which is not an equivalence\n"+      where+        txt0 = insert expr++prettyTypeMessage (IncomparableExpression expr) = ErrorMessages {..}+  where+    short = "Incomparable expression\n"++    hints = []++    long =+        "Explanation: You can use an ❰assert❱ to compare two terms for equivalence, like \n\+        \this:                                                                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────┐                                                      \n\+        \    │ assert : 2 + 2 ≡ 4 │  This is valid because ❰2 + 2❱ and ❰4❱ are both terms\n\+        \    └────────────────────┘                                                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but you cannot compare expressions, that are not terms, such as types.  For \n\+        \example, the following equivalence is " <> _NOT <> " valid:                     \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────┐                                              \n\+        \    │ assert : Natural ≡ Natural │  Invalid: ❰Natural❱ is a type, not a term    \n\+        \    └────────────────────────────┘                                              \n\+        \                                                                                \n\+        \                                                                                \n\+        \You tried to compare the following expression:                                  \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which is not a term\n"+      where+        txt0 = insert expr++prettyTypeMessage (EquivalenceTypeMismatch l _L r _R) = ErrorMessages {..}+  where+    short = "The two sides of the equivalence have different types"++    hints = []++    long =+        "Explanation: You can use ❰≡❱ to compare two terms of the same type for          \n\+        \equivalence, like this:                                                         \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────┐                                                               \n\+        \    │ 2 + 2 ≡ 4 │  This is valid because ❰2 + 2❱ and ❰4❱ have the same type     \n\+        \    └───────────┘                                                               \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but you cannot compare expressions, that have different types.  For example,\n\+        \the following assertion is " <> _NOT <> " valid:                                \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────┐                                                                \n\+        \    │ 1 ≡ True │  Invalid: ❰1❱ has type ❰Natural❱, ❰True❱ has type ❰Bool❱       \n\+        \    └──────────┘                                                                \n\+        \                                                                                \n\+        \                                                                                \n\+        \You tried to compare the following expressions:                                 \n\+        \                                                                                \n\+        \" <> insert l <> "\n\+        \                                                                                \n\+        \... which has type\n\+        \                                                                                \n\+        \" <> insert _L <> "\n\+        \                                                                                \n\+        \... and\n\+        \                                                                                \n\+        \" <> insert r <> "\n\+        \                                                                                \n\+        \... which has type\n\+        \                                                                                \n\+        \" <> insert _R <> "\n"++prettyTypeMessage (NotWithARecord expr0 expr1) = ErrorMessages {..}+  where+    short = "❰with❱ only works on records"++    hints = []++    long =+        "Explanation: You can use ❰with❱ to update a record, like this:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────┐                                                 \n\+        \    │  { a = 5 } with b = 10  │  This is valid because ❰{ a = 5}❱ is a record   \n\+        \    └────────────────────────┘                                                  \n\+        \                                                                                \n\+        \    ┌──────────────────────────────────────────┐                                \n\+        \    │  λ(r : { a : Natural }) → r with b = 10  │  This is also valid because    \n\+        \    └──────────────────────────────────────────┘  ❰r❱ is a record               \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but you cannot use ❰with❱ to update an expression that is not a record.  For\n\+        \example, the following expression is " <> _NOT <> " valid:                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────┐                                                           \n\+        \    │ 1 with b = 10 │  Invalid: ❰1❱ is not a record                             \n\+        \    └───────────────┘                                                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \You tried to update the following expressions:                                  \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which has type\n\+        \                                                                                \n\+        \" <> txt1 <> "\n\+        \                                                                                \n\+        \... which is not a record type\n"+      where+        txt0 = insert expr0+        txt1 = insert expr1++prettyTypeMessage (CantAnd expr0 expr1) =+        buildBooleanOperator "&&" expr0 expr1++prettyTypeMessage (CantOr expr0 expr1) =+        buildBooleanOperator "||" expr0 expr1++prettyTypeMessage (CantEQ expr0 expr1) =+        buildBooleanOperator "==" expr0 expr1++prettyTypeMessage (CantNE expr0 expr1) =+        buildBooleanOperator "!=" expr0 expr1++prettyTypeMessage (CantInterpolate expr0 expr1) = ErrorMessages {..}+  where+    short = "You can only interpolate ❰Text❱"++    hints = []++    long =+        "Explanation: Text interpolation only works on expressions of type ❰Text❱        \n\+        \                                                                                \n\+        \For example, these are all valid uses of string interpolation:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────┐                                                        \n\+        \    │ \"ABC${\"DEF\"}GHI\" │                                                        \n\+        \    └──────────────────┘                                                        \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────┐                                              \n\+        \    │ λ(x : Text) → \"ABC${x}GHI\" │                                              \n\+        \    └────────────────────────────┘                                              \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────────────────────────────┐                           \n\+        \    │ λ(age : Natural) → \"Age: ${Natural/show age}\" │                           \n\+        \    └───────────────────────────────────────────────┘                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● You might have thought that string interpolation automatically converts the   \n\+        \  interpolated value to a ❰Text❱ representation of that value:                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────────────────┐                                        \n\+        \    │ λ(age : Natural) → \"Age: ${age}\" │                                        \n\+        \    └──────────────────────────────────┘                                        \n\+        \                                  ⇧                                             \n\+        \                                  Invalid: ❰age❱ has type ❰Natural❱             \n\+        \                                                                                \n\+        \                                                                                \n\+        \● You might have forgotten to escape a string interpolation that you wanted     \n\+        \  Dhall to ignore and pass through:                                             \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────┐                                                          \n\+        \    │ \"echo ${HOME}\" │                                                          \n\+        \    └────────────────┘                                                          \n\+        \             ⇧                                                                  \n\+        \             ❰HOME❱ is not in scope and this might have meant to use ❰\\${HOME}❱\n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You interpolated this expression:                                               \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which does not have type ❰Text❱ but instead has type:                       \n\+        \                                                                                \n\+        \" <> txt1 <> "\n"+      where+        txt0 = insert expr0+        txt1 = insert expr1++prettyTypeMessage (CantTextAppend expr0 expr1) = ErrorMessages {..}+  where+    short = "❰++❱ only works on ❰Text❱"++    hints = []++    long =+        "Explanation: The ❰++❱ operator expects two arguments that have type ❰Text❱      \n\+        \                                                                                \n\+        \For example, this is a valid use of ❰++❱:                                       \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────┐                                                          \n\+        \    │ \"ABC\" ++ \"DEF\" │                                                          \n\+        \    └────────────────┘                                                          \n\+        \                                                                                \n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● You might have thought that ❰++❱ was the operator to combine two lists:       \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────┐                                                  \n\+        \    │ [1, 2, 3] ++ [4, 5, 6] │  Not valid                                       \n\+        \    └────────────────────────┘                                                  \n\+        \                                                                                \n\+        \                                                                                \n\+        \  ... but the list concatenation operator is actually ❰#❱:                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────┐                                                   \n\+        \    │ [1, 2, 3] # [4, 5, 6] │  Valid                                            \n\+        \    └───────────────────────┘                                                   \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You provided this argument:                                                     \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which does not have type ❰Text❱ but instead has type:                       \n\+        \                                                                                \n\+        \" <> txt1 <> "\n"+      where+        txt0 = insert expr0+        txt1 = insert expr1++prettyTypeMessage (CantListAppend expr0 expr1) = ErrorMessages {..}+  where+    short = "❰#❱ only works on ❰List❱s"++    hints = []++    long =+        "Explanation: The ❰#❱ operator expects two arguments that are both ❰List❱s       \n\+        \                                                                                \n\+        \For example, this is a valid use of ❰#❱:                                        \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────────┐                                                   \n\+        \    │ [1, 2, 3] # [4, 5, 6] │                                                   \n\+        \    └───────────────────────┘                                                   \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You provided this argument:                                                     \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which is not a ❰List❱ but instead has type:                                 \n\+        \                                                                                \n\+        \" <> txt1 <> "\n"+      where+        txt0 = insert expr0+        txt1 = insert expr1++prettyTypeMessage (CantAdd expr0 expr1) =+        buildNaturalOperator "+" expr0 expr1++prettyTypeMessage (CantMultiply expr0 expr1) =+        buildNaturalOperator "*" expr0 expr1++prettyTypeMessage OptionalWithTypeMismatch = ErrorMessages {..}+  where+    short = "❰with❱ cannot change the type of an ❰Optional❱ value"+    hints = []+    long =+        "Explanation: The ❰with❱ keyword cannot change the type of a value stored inside \n\+        \of a ❰Some❱ constructor                                                         \n\+        \                                                                                \n\+        \For example, this is a valid use of ❰with❱:                                     \n\+        \                                                                                \n\+        \                                                                                \n\+        \           The old value has type ❰Natural❱                                     \n\+        \           ⇩                                                                    \n\+        \    ┌───────────────────┐                                                       \n\+        \    │ Some 1 with ? = 2 │                                                       \n\+        \    └───────────────────┘                                                       \n\+        \                      ⇧                                                         \n\+        \                      ... which matches the type of the new value, which is also\n\+        \                      ❰Natural❱                                                 \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but the following example is not valid:                                     \n\+        \                                                                                \n\+        \                                                                                \n\+        \           The old value has type ❰Natural❱                                     \n\+        \           ⇩                                                                    \n\+        \    ┌──────────────────────┐                                                    \n\+        \    │ Some 1 with ? = True │                                                    \n\+        \    └──────────────────────┘                                                    \n\+        \                      ⇧                                                         \n\+        \                      ... but the new value has type ❰Bool❱, which does not     \n\+        \                      match                                                     \n"++prettyTypeMessage NotALabelPath = ErrorMessages {..}+  where+    short = "Use a label to update a record"+    hints = []+    long =+        "Explanation: The ❰with❱ keyword supports updating records by naming the field(s)\n\+        \to update, but you provided a path component of ❰?❱, which only works on        \n\+        \❰Optional❱ values and not records.                                              \n\+        \                                                                                \n\+        \For example, these are valid uses of ❰with❱ to update a record:                 \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────┐                                                    \n\+        \    │ { x = 1 } with x = 2 │                                                    \n\+        \    └──────────────────────┘                                                    \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────────────┐                                          \n\+        \    │ { x = { y = 1 } } with x.y = 2 │                                          \n\+        \    └────────────────────────────────┘                                          \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but the following example is not valid:                                     \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────┐                                                    \n\+        \    │ { x = 1 } with ? = 2 │                                                    \n\+        \    └──────────────────────┘                                                    \n\+        \                     ⇧                                                          \n\+        \                     This path component is reserved for updating ❰Optional❱    \n\+        \                     values and not records                                     \n\+        \                                                                                \n\+        \Note that you can update a field named ❰?❱ if you escape the path component,    \n\+        \though:                                                                         \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌────────────────────────┐                                                  \n\+        \    │ { ? = 1 } with `?` = 2 │                                                  \n\+        \    └────────────────────────┘                                                  \n"++prettyTypeMessage (NotAQuestionPath k) = ErrorMessages {..}+  where+    short = "Use ❰?❱ to update an ❰Optional❱ value"+    hints = []+    long =+        "Explanation: The ❰with❱ keyword supports updating ❰Optional❱ values using a path\n\+        \component of ❰?❱, but you provided a path component other than ❰?❱.             \n\+        \                                                                                \n\+        \For example, these are valid uses of ❰with❱ to update an ❰Optional❱ value:      \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────────┐                                                       \n\+        \    │ Some 1 with ? = 2 │                                                       \n\+        \    └───────────────────┘                                                       \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────┐                                             \n\+        \    │ { x = Some 1 } with x.? = 2 │                                             \n\+        \    └─────────────────────────────┘                                             \n\+        \                                                                                \n\+        \                                                                                \n\+        \... but the following example is not valid:                                     \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌──────────────────────┐                                                    \n\+        \    │ Some 1 with x = True │                                                    \n\+        \    └──────────────────────┘                                                    \n\+        \                  ⇧                                                             \n\+        \                  This path component should have been ❰?❱                      \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You provided this path component:                                               \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which perhaps should have been ❰?❱.                                         \n"+      where+        txt0 = insert k++prettyTypeMessage ShowConstructorNotOnUnion = ErrorMessages {..}+  where+      short = "ShowConstructorNotOnUnion"+      hints = []+      long = ""++buildBooleanOperator :: Pretty a => Text -> Expr s a -> Expr s a -> ErrorMessages+buildBooleanOperator operator expr0 expr1 = ErrorMessages {..}+  where+    short = "❰" <> txt2 <> "❱ only works on ❰Bool❱s"++    hints = []++    long =+        "Explanation: The ❰" <> txt2 <> "❱ operator expects two arguments that have type ❰Bool❱\n\+        \                                                                                \n\+        \For example, this is a valid use of ❰" <> txt2 <> "❱:                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────────────┐                                                           \n\+        \    │ True " <> txt2 <> " False │                                               \n\+        \    └───────────────┘                                                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \You provided this argument:                                                     \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which does not have type ❰Bool❱ but instead has type:                       \n\+        \                                                                                \n\+        \" <> txt1 <> "\n"+      where+        txt0 = insert expr0+        txt1 = insert expr1++    txt2 = pretty operator++buildNaturalOperator :: Pretty a => Text -> Expr s a -> Expr s a -> ErrorMessages+buildNaturalOperator operator expr0 expr1 = ErrorMessages {..}+  where+    short = "❰" <> txt2 <> "❱ only works on ❰Natural❱s"++    hints = []++    long =+        "Explanation: The ❰" <> txt2 <> "❱ operator expects two arguments that have type ❰Natural❱\n\+        \                                                                                \n\+        \For example, this is a valid use of ❰" <> txt2 <> "❱:                           \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────┐                                                                   \n\+        \    │ 3 " <> txt2 <> " 5 │                                                      \n\+        \    └───────┘                                                                   \n\+        \                                                                                \n\+        \                                                                                \n\+        \Some common reasons why you might get this error:                               \n\+        \                                                                                \n\+        \● You might have tried to use an ❰Integer❱, which is " <> _NOT <> " allowed:    \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────────────────────────────────────┐                                 \n\+        \    │ λ(x : Integer) → λ(y : Integer) → x " <> txt2 <> " y │  Not valid         \n\+        \    └─────────────────────────────────────────┘                                 \n\+        \                                                                                \n\+        \                                                                                \n\+        \  You can only use ❰Natural❱ numbers                                            \n\+        \                                                                                \n\+        \                                                                                \n\+        \● You might have mistakenly used an ❰Integer❱ literal, which is " <> _NOT <> " allowed:\n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌─────────┐                                                                 \n\+        \    │ +2 " <> txt2 <> " +2 │  Not valid                                         \n\+        \    └─────────┘                                                                 \n\+        \                                                                                \n\+        \                                                                                \n\+        \  You need to remove the leading ❰+❱ to transform them into ❰Natural❱ literals, \n\+        \  like this:                                                                    \n\+        \                                                                                \n\+        \                                                                                \n\+        \    ┌───────┐                                                                   \n\+        \    │ 2 " <> txt2 <> " 2 │  Valid                                               \n\+        \    └───────┘                                                                   \n\+        \                                                                                \n\+        \                                                                                \n\+        \────────────────────────────────────────────────────────────────────────────────\n\+        \                                                                                \n\+        \You provided this argument:                                                     \n\+        \                                                                                \n\+        \" <> txt0 <> "\n\+        \                                                                                \n\+        \... which does not have type ❰Natural❱ but instead has type:                    \n\+        \                                                                                \n\+        \" <> txt1 <> "\n"+      where+        txt0 = insert expr0+        txt1 = insert expr1++    txt2 = pretty operator++-- | A structured type error that includes context+data TypeError s a = TypeError+    { context     :: Context (Expr s a)+    , current     :: Expr s a+    , typeMessage :: TypeMessage s a+    }++instance (Eq a, Pretty s, Pretty a) => Show (TypeError s a) where+    show = Pretty.renderString . Dhall.Pretty.layout . prettyTypeError++instance (Eq a, Pretty s, Pretty a, Typeable s, Typeable a) => Exception (TypeError s a)++instance (Eq a, Pretty s, Pretty a) => Pretty (TypeError s a) where+    pretty = Pretty.unAnnotate . prettyTypeError++prettyTypeError :: (Eq a, Pretty s, Pretty a) => TypeError s a -> Doc Ann+prettyTypeError (TypeError _ expr msg) =+    (   "\n"+    <>  shortTypeMessage msg <> "\n"+    <>  source+    )+  where+    source = case expr of+        Note s _ -> pretty s+        _        -> mempty++{-| Wrap a type error in this exception type to censor source code and+    `Dhall.Syntax.Text` literals from the error message+-}+data Censored+    = CensoredDetailed (DetailedTypeError Src X)+    | Censored (TypeError Src X)++instance Show Censored where+    show = Pretty.renderString . Dhall.Pretty.layout . Pretty.pretty++instance Exception Censored++instance Pretty Censored where+    pretty (CensoredDetailed (DetailedTypeError e)) =+        pretty (DetailedTypeError (censorTypeError e))+    pretty (Censored e) = pretty (censorTypeError e)++censorTypeError :: TypeError Src a -> TypeError Src a+censorTypeError (TypeError c e m) = TypeError c' e' m'+  where+    c' = fmap Dhall.Core.censorExpression c++    e' = Dhall.Core.censorExpression e++    m' = over messageExpressions Dhall.Core.censorExpression m++-- | @Traversal@ that traverses every `Expr` in a `TypeMessage`+messageExpressions+    :: Applicative f+    => (Expr s a -> f (Expr t b)) -> TypeMessage s a -> f (TypeMessage t b)+messageExpressions f m = case m of+    UnboundVariable a ->+        UnboundVariable <$> pure a+    InvalidInputType a ->+        InvalidInputType <$> f a+    InvalidOutputType a ->+        InvalidOutputType <$> f a+    NotAFunction a b ->+        NotAFunction <$> f a <*> f b+    TypeMismatch a b c d ->+        TypeMismatch <$> f a <*> f b <*> f c <*> f d+    AnnotMismatch a b c ->+        AnnotMismatch <$> f a <*> f b <*> f c+    Untyped ->+        pure Untyped+    MissingListType ->+        pure MissingListType+    MismatchedListElements a b c d ->+        MismatchedListElements <$> pure a <*> f b <*> f c <*> f d+    InvalidListType a ->+        InvalidListType <$> f a+    ListLitInvariant ->+        pure ListLitInvariant+    InvalidSome a b c ->+        InvalidSome <$> f a <*> f b <*> f c+    InvalidPredicate a b ->+        InvalidPredicate <$> f a <*> f b+    IfBranchMismatch a b c d ->+        IfBranchMismatch <$> f a <*> f b <*> f c <*> f d+    InvalidFieldType a b ->+        InvalidFieldType <$> pure a <*> f b+    InvalidAlternativeType a b ->+        InvalidAlternativeType <$> pure a <*> f b+    ListAppendMismatch a b ->+        ListAppendMismatch <$> f a <*> f b+    InvalidDuplicateField a b c ->+        InvalidDuplicateField a <$> f b <*> f c+    MustCombineARecord a b c ->+        MustCombineARecord <$> pure a <*> f b <*> f c+    InvalidRecordCompletion a l ->+        InvalidRecordCompletion a <$> f l+    CompletionSchemaMustBeARecord l r ->+        CompletionSchemaMustBeARecord <$> f l <*> f r+    CombineTypesRequiresRecordType a b ->+        CombineTypesRequiresRecordType <$> f a <*> f b+    DuplicateFieldCannotBeMerged a ->+        pure (DuplicateFieldCannotBeMerged a)+    FieldCollision a ->+        pure (FieldCollision a)+    FieldTypeCollision a ->+        pure (FieldTypeCollision a)+    MustMergeARecord a b ->+        MustMergeARecord <$> f a <*> f b+    MustMergeUnionOrOptional a b ->+        MustMergeUnionOrOptional <$> f a <*> f b+    MustMapARecord a b ->+        MustMapARecord <$> f a <*> f b+    InvalidToMapRecordKind a b ->+        InvalidToMapRecordKind <$> f a <*> f b+    HeterogenousRecordToMap a b c ->+        HeterogenousRecordToMap <$> f a <*> f b <*> f c+    InvalidToMapType a ->+        InvalidToMapType <$> f a+    MapTypeMismatch a b ->+        MapTypeMismatch <$> f a <*> f b+    MissingToMapType ->+        pure MissingToMapType+    UnusedHandler a ->+        UnusedHandler <$> pure a+    MissingHandler e a ->+        MissingHandler <$> pure e <*> pure a+    HandlerInputTypeMismatch a b c ->+        HandlerInputTypeMismatch <$> pure a <*> f b <*> f c+    DisallowedHandlerType a b c d ->+        DisallowedHandlerType <$> pure a <*> f b <*> f c <*> pure d+    HandlerOutputTypeMismatch a b c d ->+        HandlerOutputTypeMismatch <$> pure a <*> f b <*> pure c <*> f d+    MissingMergeType ->+        pure MissingMergeType+    HandlerNotAFunction a b ->+        HandlerNotAFunction <$> pure a <*> f b+    CantAccess a b c ->+        CantAccess <$> pure a <*> f b <*> f c+    CantProject a b c ->+        CantProject <$> pure a <*> f b <*> f c+    CantProjectByExpression a ->+        CantProjectByExpression <$> f a+    DuplicateProjectionLabel a ->+        pure (DuplicateProjectionLabel a)+    MissingField a b ->+        MissingField <$> pure a <*> f b+    MissingConstructor a b ->+        MissingConstructor <$> pure a <*> f b+    ProjectionTypeMismatch a b c d e ->+        ProjectionTypeMismatch <$> pure a <*> f b <*> f c <*> f d <*> f e+    AssertionFailed a b ->+        AssertionFailed <$> f a <*> f b+    NotAnEquivalence a ->+        NotAnEquivalence <$> f a+    IncomparableExpression a ->+        IncomparableExpression <$> f a+    EquivalenceTypeMismatch a b c d ->+        EquivalenceTypeMismatch <$> f a <*> f b <*> f c <*> f d+    NotWithARecord a b ->+        NotWithARecord <$> f a <*> f b+    CantAnd a b ->+        CantAnd <$> f a <*> f b+    CantOr a b ->+        CantOr <$> f a <*> f b+    CantEQ a b ->+        CantEQ <$> f a <*> f b+    CantNE a b ->+        CantNE <$> f a <*> f b+    CantInterpolate a b ->+        CantInterpolate <$> f a <*> f b+    CantTextAppend a b ->+        CantTextAppend <$> f a <*> f b+    CantListAppend a b ->+        CantListAppend <$> f a <*> f b+    CantAdd a b ->+        CantAdd <$> f a <*> f b+    CantMultiply a b ->+        CantMultiply <$> f a <*> f b+    OptionalWithTypeMismatch ->+        pure OptionalWithTypeMismatch+    NotALabelPath ->+        pure NotALabelPath+    NotAQuestionPath k ->+        pure (NotAQuestionPath k)+    ShowConstructorNotOnUnion ->+        pure ShowConstructorNotOnUnion++{-| Newtype used to wrap error messages so that they render with a more+    detailed explanation of what went wrong+-}+newtype DetailedTypeError s a = DetailedTypeError (TypeError s a)+    deriving (Typeable)++instance (Eq a, Pretty s, Pretty a) => Show (DetailedTypeError s a) where+    show = Pretty.renderString . Dhall.Pretty.layout . prettyDetailedTypeError++instance (Eq a, Pretty s, Pretty a, Typeable s, Typeable a) => Exception (DetailedTypeError s a)++instance (Eq a, Pretty s, Pretty a) => Pretty (DetailedTypeError s a) where+    pretty = Pretty.unAnnotate . prettyDetailedTypeError++prettyDetailedTypeError :: (Eq a, Pretty s, Pretty a) => DetailedTypeError s a -> Doc Ann+prettyDetailedTypeError (DetailedTypeError (TypeError ctx expr msg)) =+    (   "\n"+    <>  (   if null (Dhall.Context.toList ctx)+            then ""+            else prettyContext ctx <> "\n\n"+        )+    <>  longTypeMessage msg <> "\n"+    <>  "────────────────────────────────────────────────────────────────────────────────\n"+    <>  "\n"+    <>  source+    )+  where+    prettyKV (key, val) =+        Dhall.Util.snipDoc+            (Dhall.Pretty.Internal.prettyLabel key <> " : " <> Dhall.Pretty.prettyExpr val)++    prettyContext =+            Pretty.vsep+        .   map prettyKV+        .   reverse+        .   Dhall.Context.toList++    source = case expr of+        Note s _ -> pretty s+        _        -> mempty++{-| This function verifies that a custom context is well-formed so that+    type-checking will not loop++    Note that `typeWith` already calls `checkContext` for you on the `Context`+    that you supply+-}+checkContext :: Context (Expr s X) -> Either (TypeError s X) ()+checkContext context =+    case Dhall.Context.match context of+        Nothing ->+            return ()+        Just (x, v, context') -> do+            let shiftedV       =       Dhall.Core.shift (-1) (V x 0)  v+            let shiftedContext = fmap (Dhall.Core.shift (-1) (V x 0)) context'+            _ <- typeWith shiftedContext shiftedV+            return ()++toPath :: (Functor list, Foldable list) => list Text -> Text+toPath ks =+    Text.intercalate "."+        (Foldable.toList (fmap (Dhall.Pretty.Internal.escapeLabel AnyLabelOrSome) ks))++duplicateElement :: Ord a => [a] -> Maybe a+duplicateElement = go Data.Set.empty+  where+    go _ [] = Nothing+    go found (x : xs)+        | Data.Set.member x found = Just x+        | otherwise               = go (Data.Set.insert x found) xs
+ src/Dhall/URL.hs view
@@ -0,0 +1,37 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards   #-}++module Dhall.URL where++import Data.Text (Text)++import Dhall.Syntax (Directory (..), File (..), Scheme (..), URL (..))++renderComponent :: Text -> Text+renderComponent component = "/" <> component++renderQuery :: Text -> Text+renderQuery query = "?" <> query++renderURL :: URL -> Text+renderURL url =+        schemeText+    <>  authority+    <>  pathText+    <>  queryText+  where+    URL {..} = url++    File {..} = path++    Directory {..} = directory++    schemeText = case scheme of+        HTTP  -> "http://"+        HTTPS -> "https://"++    pathText =+            foldMap renderComponent (reverse components)+        <>  renderComponent file++    queryText = foldMap renderQuery query
src/Dhall/Util.hs view
@@ -1,4 +1,6 @@+{-# LANGUAGE NamedFieldPuns    #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards   #-}  -- | Shared utility functions @@ -7,18 +9,47 @@     , snipDoc     , insert     , _ERROR+    , _WARNING+    , printWarning+    , Censor(..)+    , Input(..)+    , Transitivity(..)+    , OutputMode(..)+    , Output(..)+    , getExpression+    , getExpressionAndHeader+    , getExpressionAndHeaderFromStdinText+    , Header(..)+    , CheckFailed(..)+    , MultipleCheckFailed(..)+    , handleMultipleChecksFailed+    , renderExpression     ) where -import Data.Monoid ((<>))-import Data.String (IsString)-import Data.Text (Text)-import Data.Text.Prettyprint.Doc (Doc, Pretty)-import Dhall.Pretty (Ann)+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.Prettyprint.Doc             as Pretty-import qualified Data.Text.Prettyprint.Doc.Render.Text as Pretty+import qualified Data.Text.IO+import qualified Dhall.Parser import qualified Dhall.Pretty+import qualified Prettyprinter                 as Pretty+import qualified Prettyprinter.Render.Terminal as Pretty.Terminal+import qualified Prettyprinter.Render.Text     as Pretty.Text+import qualified System.Console.ANSI           as ANSI+import qualified System.IO                     as IO  -- | Utility function to cut out the interior of a large text block snip :: Text -> Text@@ -50,7 +81,7 @@      preview =             Data.Text.unlines header-        <>  separator <> "\n"+        <>  Data.Text.take 80 separator <> "\n"         <>  Data.Text.unlines footer  {-| Like `snip`, but for `Doc`s@@ -61,11 +92,11 @@ snipDoc :: Doc Ann -> Doc a snipDoc doc = Pretty.align (Pretty.pretty (snip text))   where-    stream = Pretty.layoutSmart Dhall.Pretty.layoutOpts doc+    stream = Dhall.Pretty.layout doc      ansiStream = fmap Dhall.Pretty.annToAnsiStyle stream -    text = Pretty.renderStrict ansiStream+    text = Pretty.Terminal.renderStrict ansiStream  takeEnd :: Int -> [a] -> [a] takeEnd n l = go (drop n l) l@@ -81,3 +112,180 @@ -- | Prefix used for error messages _ERROR :: IsString string => string _ERROR = "\ESC[1;31mError\ESC[0m"++-- | Prefix used for error messages+_WARNING :: IsString string => string+_WARNING = "\ESC[1;33mWarning\ESC[0m"++-- | Output a warning message on stderr.+printWarning :: (MonadIO m) => String -> m ()+printWarning message = do+    let warning =+                "\n"+            <> _WARNING+            <> ": "+            <> message++    liftIO $ IO.hPutStrLn IO.stderr warning++get+    :: (String -> Text -> Either ParseError a)+    -> Censor+    -> InputOrTextFromStdin+    -> IO a+get parser censor input = do+    inText <-+        case input of+            Input_ (InputFile file) -> Data.Text.IO.readFile file+            Input_ StandardInput    -> Data.Text.IO.getContents+            StdinText _ text        -> pure text++    let name =+            case input of+                Input_ (InputFile file) -> file+                Input_ StandardInput    -> "(input)"+                StdinText inputName _   -> inputName++    let result = parser name inText++    let censoredResult =+            case censor of+                NoCensor -> result+                Censor   -> first Dhall.Parser.censor result++    throws censoredResult++{-| Convenience utility for converting `Either`-based exceptions to `IO`-based+    exceptions+-}+throws :: (Exception e, MonadIO io) => Either e a -> io a+throws (Left  e) = liftIO (Control.Exception.throwIO e)+throws (Right r) = return r++-- | Set to `Censor` if you want to censor error text that might include secrets+data Censor = NoCensor | Censor++-- | Path to input+data Input = StandardInput | InputFile FilePath deriving (Eq)++-- | Path to input or raw input text, necessary since we can't read STDIN twice+data InputOrTextFromStdin+    = Input_ Input+    | StdinText String Text+    -- ^ @StdinText name text@ where name is a user-friendly name describing the+    -- input expression, used in parsing error messages++{-| Specifies whether or not an input's transitive dependencies should also be+    processed.  Transitive dependencies are restricted to relative file imports.+-}+data Transitivity+    = NonTransitive+    -- ^ Do not process transitive dependencies+    | Transitive+    -- ^ Process transitive dependencies in the same way++-- | Path to output+data Output = StandardOutput | OutputFile FilePath++{-| Some command-line subcommands can either `Write` their input or `Check`+    that the input has already been modified.  This type is shared between them+    to record that choice.+-}+data OutputMode = Write | Check++-- | A check failure corresponding to a single input.+-- This type is intended to be used with 'MultipleCheckFailed' for error+-- reporting.+newtype CheckFailed = CheckFailed { input :: Input }++-- | Exception thrown when the @--check@ flag to a command-line subcommand fails+data MultipleCheckFailed = MultipleCheckFailed+  { command :: Text+  , modified :: Text+  , inputs :: NonEmpty Input+  }++instance Exception MultipleCheckFailed++instance Show MultipleCheckFailed where+    show MultipleCheckFailed{..} =+         _ERROR <> ": ❰dhall " <> command_ <> " --check❱ failed on:\n\+        \\n" <> files <>+        "\n\+        \You ran ❰dhall " <> command_ <> " --check❱, but the input appears to have not\n\+        \been " <> modified_ <> " before, or was changed since the last time the input\n\+        \was " <> modified_ <> ".\n"+      where+        modified_ = Data.Text.unpack modified++        command_ = Data.Text.unpack command++        files = unlines . map format $ toList inputs++        format input = case input of+            StandardInput -> "↳ (stdin)"+            InputFile file -> "↳ " <> file++-- | Run IO for multiple inputs, then collate all the check failures before+-- throwing if there was any failure+handleMultipleChecksFailed+    :: (Foldable t, Traversable t)+    => Text+    -> Text+    -> (a -> IO (Either CheckFailed ()))+    -> t a+    -> IO ()+handleMultipleChecksFailed command modified f xs = post =<< mapM f xs+  where+    post results =+        case lefts (toList results) of+            [] -> pure ()+            cf:cfs -> Control.Exception.throwIO $ MultipleCheckFailed+                { command+                , modified+                , inputs = fmap input (cf:|cfs)+                }++-- | Convenient utility for retrieving an expression+getExpression :: Censor -> Input -> IO (Expr Src Import)+getExpression censor = get Dhall.Parser.exprFromText censor . Input_++-- | Convenient utility for retrieving an expression along with its header+getExpressionAndHeader :: Censor -> Input -> IO (Header, Expr Src Import)+getExpressionAndHeader censor =+    get Dhall.Parser.exprAndHeaderFromText censor . Input_++-- | Convenient utility for retrieving an expression along with its header from+-- | text already read from STDIN (so it's not re-read)+getExpressionAndHeaderFromStdinText+    :: Censor -> String -> Text -> IO (Header, Expr Src Import)+getExpressionAndHeaderFromStdinText censor inputName =+    get Dhall.Parser.exprAndHeaderFromText censor . StdinText inputName++{-| Convenient utility to output an expression either to a file+    or to stdout.+-}+renderExpression :: Pretty a => CharacterSet -> Bool -> Maybe FilePath -> Expr Src a -> IO ()+renderExpression characterSet plain output expression = do+    let document = Dhall.Pretty.prettyCharacterSet characterSet expression++    let stream = Dhall.Pretty.layout document++    case output of+        Nothing -> do+            supportsANSI <- ANSI.hSupportsANSI IO.stdout++            let ansiStream =+                    if supportsANSI && not plain+                    then fmap Dhall.Pretty.annToAnsiStyle stream+                    else Pretty.unAnnotateS stream++            Pretty.Terminal.renderIO IO.stdout ansiStream++            Data.Text.IO.putStrLn ""++        Just file_ ->+            IO.withFile file_ IO.WriteMode $ \h -> do+                Pretty.Text.renderIO h stream++                Data.Text.IO.hPutStrLn h ""
+ src/Dhall/Version.hs view
@@ -0,0 +1,17 @@+{-| Utilities for getting the current version of the Haskell implementation of+    Dhall+-}+module Dhall.Version ( dhallVersion+                     , dhallVersionString+                     ) where++import qualified Data.Version as V+import qualified Paths_dhall  as P++-- | The current `V.Version` of the Haskell implementation+dhallVersion :: V.Version+dhallVersion = P.version++-- | The current version `String` for the Haskell implementation+dhallVersionString :: String+dhallVersionString = V.showVersion dhallVersion
tests/Dhall/Test/Dhall.hs view
@@ -1,101 +1,178 @@+{-# LANGUAGE BangPatterns        #-} {-# LANGUAGE DeriveAnyClass      #-}+{-# LANGUAGE DeriveFunctor       #-} {-# LANGUAGE DeriveGeneric       #-}+{-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE OverloadedLists     #-} {-# LANGUAGE OverloadedStrings   #-} {-# LANGUAGE RecordWildCards     #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE StandaloneDeriving  #-}+{-# LANGUAGE TypeFamilies        #-}  {-# OPTIONS_GHC -fno-warn-orphans #-}  module Dhall.Test.Dhall where -import Control.Exception (SomeException, try)-import Data.Text (Text)-import Dhall (Inject, Interpret)-import Dhall.Core (Expr(..))-import GHC.Generics (Generic)-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 import qualified Dhall.Import import qualified Dhall.Map import qualified Dhall.Parser +data ExprF expr+   = LitF Natural+   | AddF expr expr+   | MulF expr expr+   deriving (Eq, Functor, Generic, FromDhall, ToDhall, Show)++instance Eq1 ExprF where+    liftEq _  (LitF aL) (LitF aR) = aL == aR+    liftEq eq (AddF aL bL) (AddF aR bR) = (aL `eq` aR) && (bL `eq` bR)+    liftEq eq (MulF aL bL) (MulF aR bR) = (aL `eq` aR) && (bL `eq` bR)+    liftEq _ _ _ = False++instance Show1 ExprF where+    liftShowsPrec _  _ d (LitF a) = showsPrec d a+    liftShowsPrec sp _ d (AddF a b) = Classes.showsBinaryWith sp sp "AddF" d a b+    liftShowsPrec sp _ d (MulF a b) = Classes.showsBinaryWith sp sp "MulF" d a b+ tests :: TestTree tests =     testGroup "Input"      [ shouldShowDetailedTypeError-     , shouldHandleBothUnionLiterals+     , shouldHandleUnionLiteral+     , shouldHaveWorkingRecursiveFromDhall      , shouldHaveWorkingGenericAuto      , shouldHandleUnionsCorrectly      , shouldTreatAConstructorStoringUnitAsEmptyAlternative+     , shouldConvertDhallToHaskellCorrectly+     , shouldConvertHaskellToDhallCorrectly+     , shouldShowCorrectErrorForInvalidDecoderInUnion      ]  data MyType = MyType { foo :: String , bar :: Natural } -wrongDhallType :: Dhall.Type MyType -wrongDhallType = Dhall.Type { .. }-  where expected =+wrongDhallType :: Dhall.Decoder MyType+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 _ = Nothing+        extract expr = Dhall.typeError expected expr  shouldShowDetailedTypeError :: TestTree shouldShowDetailedTypeError = testCase "detailed TypeError" $ do   inputEx :: Either SomeException MyType <--        try ( Dhall.input wrongDhallType "{  bar = 0, foo = \"foo\" }") +        try ( Dhall.input wrongDhallType "{  bar = 0, foo = \"foo\" }")    let expectedMsg =-        "\ESC[1;31mError\ESC[0m: Invalid Dhall.Type                                                  \n\+        "\ESC[1;31mError\ESC[0m: Invalid Dhall.Decoder                                               \n\         \                                                                                \n\-        \Every Type must provide an extract function that succeeds if an expression      \n\-        \matches the expected type.  You provided a Type that disobeys this contract     \n\+        \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 Type provided has the expected dhall type:                                  \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"    let assertMsg = "The exception message did not match the expected output"-  +   case inputEx of     Left ex -> assertEqual assertMsg expectedMsg (show ex)-    Right _ -> fail "The extraction using a wrong type succeded"+    Right _ -> fail "The extraction using a wrong type succeeded"  -- https://github.com/dhall-lang/dhall-haskell/issues/915-shouldHandleBothUnionLiterals :: TestTree-shouldHandleBothUnionLiterals = testCase "Marshal union literals" $ do-    let example :: Dhall.Type Bool+shouldHandleUnionLiteral :: TestTree+shouldHandleUnionLiteral = testCase "Marshal union literals" $ do+    let example :: Dhall.Decoder Bool         example = Dhall.union (Dhall.constructor "Test" Dhall.bool)      _ <- Dhall.input example "< Test : Bool >.Test True"-    _ <- Dhall.input example "< Test = True >"      return ()  shouldTreatAConstructorStoringUnitAsEmptyAlternative :: TestTree shouldTreatAConstructorStoringUnitAsEmptyAlternative = testCase "Handle unit constructors" $ do-    let exampleType :: Dhall.Type ()+    let exampleType :: Dhall.Decoder ()         exampleType = Dhall.union (Dhall.constructor "A" Dhall.unit)      () <- Dhall.input exampleType "< A >.A" -    let exampleInputType :: Dhall.InputType ()-        exampleInputType = Dhall.inputUnion (Dhall.inputConstructor "A")+    let exampleEncoder :: Dhall.Encoder ()+        exampleEncoder = Dhall.unionEncoder (Dhall.encodeConstructor "A") -    Dhall.embed exampleInputType () @=? 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 =+        Fix+            (AddF+                (Fix (MulF (Fix (LitF 3)) (Fix (LitF 7))))+                (Fix (AddF (Fix (LitF 1)) (Fix (LitF 2))))+            )+ data CompilerFlavor3 =   GHC3 | GHCJS3 | Helium3   deriving (Generic, Show, Eq)@@ -117,85 +194,305 @@   ]  data NonEmptyUnion = N0 Bool | N1 Natural | N2 Text-    deriving (Eq, Generic, Inject, Interpret, Show)+    deriving (Eq, Generic, ToDhall, FromDhall, Show)  data Enum = E0 | E1 | E2-    deriving (Eq, Generic, Inject, Interpret, Show)+    deriving (Eq, Generic, ToDhall, FromDhall, Show) -data Mixed = M0 Bool | M1 | M2 ()-    deriving (Eq, Generic, Inject, Interpret, Show)+data Records+    = R0 {}+    | R1 { a :: () }+    | R2 { x :: Double }+    | R3 { a :: (), b :: () }+    | R4 { x :: Double, y :: Double }+    deriving (Eq, Generic, ToDhall, FromDhall, Show) -deriving instance Interpret ()+data Products = P0 | P1 () | P2 Double | P3 () () | P4 Double Double+    deriving (Eq, Generic, ToDhall, FromDhall, Show)  shouldHandleUnionsCorrectly :: TestTree shouldHandleUnionsCorrectly =   testGroup "Handle union literals"     [ "λ(x : < N0 : { _1 : Bool } | N1 : { _1 : Natural } | N2 : { _1 : Text } >) → x"-        `shouldPassThrough` [ N0 True, N1 5, N2 "ABC" ]+        `shouldPassThroughWrapped` [ N0 True, N1 5, N2 "ABC" ]     , "λ(x : < E0 | E1 | E2 >) → x"-        `shouldPassThrough` [ E0, E1, E2 ]-    , "λ(x : < M0 : { _1 : Bool } | M1 | M2 : { _1 : {} } >) → x"-        `shouldPassThrough` [ M0 True, M1, M2 () ]+        `shouldPassThroughWrapped` [ E0, E1, E2 ]+    , "λ(x : < R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >) → x"+        `shouldPassThroughWrapped` [ R0 {}, R1 { a = () }, R2 { x = 1.0 }, R3 { a = (), b = () }, R4 { x = 1.0, y = 2.0 } ]+    , "λ(x : < P0 | P1 : { _1 : {} } | P2 : { _1 : Double } | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >) → x"+        `shouldPassThroughWrapped` [ P0 , P1 (), P2 1.0, P3 () (), P4 1.0 2.0 ] +    , "λ(x : < N0 : Bool | N1 : Natural | N2 : Text >) → x"+        `shouldPassThroughSmart` [ N0 True, N1 5, N2 "ABC" ]+    , "λ(x : < R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >) → x"+        `shouldPassThroughSmart` [ R0 {}, R1 { a = () }, R2 { x = 1.0 }, R3 { a = (), b = () }, R4 { x = 1.0, y = 2.0 } ]+    , "λ(x : < P0 | P1 | P2 : Double | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >) → x"+        `shouldPassThroughSmart` [ P0 , P1 (), P2 1.0, P3 () (), P4 1.0 2.0 ]+     , "(< N0 : { _1 : Bool } | N1 : { _1 : Natural } | N2 : { _1 : Text } >).N0 { _1 = True }"-        `shouldMarshalInto` N0 True+        `shouldMarshalIntoWrapped` N0 True     , "(< N0 : { _1 : Bool } | N1 : { _1 : Natural } | N2 : { _1 : Text } >).N1 { _1 = 5 }"-        `shouldMarshalInto` N1 5+        `shouldMarshalIntoWrapped` N1 5     , "(< N0 : { _1 : Bool } | N1 : { _1 : Natural } | N2 : { _1 : Text } >).N2 { _1 = \"ABC\" }"-        `shouldMarshalInto` N2 "ABC" -    , "< N0 = { _1 = True } | N1 : { _1 : Natural } | N2 : { _1 : Text } >"-        `shouldMarshalInto` N0 True-    , "< N0 : { _1 : Bool } | N1 = { _1 = 5 } | N2 : { _1 : Text } >"-        `shouldMarshalInto` N1 5-    , "< N0 : { _1 : Bool } | N1 : { _1 : Natural } | N2 = { _1 = \"ABC\" } >"-        `shouldMarshalInto` N2 "ABC"+        `shouldMarshalIntoWrapped` N2 "ABC" -    , "(< E0 | E1 | E2>).E0" `shouldMarshalInto` E0-    , "(< E0 | E1 | E2>).E1" `shouldMarshalInto` E1-    , "(< E0 | E1 | E2>).E2" `shouldMarshalInto` E2+    , "(< N0 : Bool | N1 : Natural | N2 : Text >).N0 True"+        `shouldMarshalIntoSmart` N0 True+    , "(< N0 : Bool | N1 : Natural | N2 : Text >).N1 5"+        `shouldMarshalIntoSmart` N1 5+    , "(< N0 : Bool | N1 : Natural | N2 : Text >).N2 \"ABC\""+        `shouldMarshalIntoSmart` N2 "ABC" -    , "(< M0 : { _1 : Bool } | M1 | M2 : { _1 : {} } >).M0 { _1 = True }"-        `shouldMarshalInto` M0 True-    , "(< M0 : { _1 : Bool } | M1 | M2 : { _1 : {} } >).M1"-        `shouldMarshalInto` M1-    , "(< M0 : { _1 : Bool } | M1 | M2 : { _1 : {} } >).M2 { _1 = {=} }"-        `shouldMarshalInto` M2 ()+    , "(< E0 | E1 | E2>).E0" `shouldMarshalIntoWrapped` E0+    , "(< E0 | E1 | E2>).E1" `shouldMarshalIntoWrapped` E1+    , "(< E0 | E1 | E2>).E2" `shouldMarshalIntoWrapped` E2 -    , "< M0 = { _1 = True } | M1 | M2 : { _1 : {} } >"-        `shouldMarshalInto` M0 True+    , "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R0"+        `shouldMarshalIntoWrapped` R0+    , "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R1 { a = {=} }"+        `shouldMarshalIntoWrapped` R1 { a = () }+    , "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R2 { x = 1.0 }"+        `shouldMarshalIntoWrapped` R2 { x = 1.0 }+    , "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R3 { a = {=}, b = {=} }"+        `shouldMarshalIntoWrapped` R3 { a = (), b = () }+    , "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R4 { x = 1.0, y = 2.0 }"+        `shouldMarshalIntoWrapped` R4 { x = 1.0, y = 2.0 } +    , "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R0"+        `shouldMarshalIntoSmart` R0+    , "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R1 { a = {=} }"+        `shouldMarshalIntoSmart` R1 { a = () }+    , "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R2 { x = 1.0 }"+        `shouldMarshalIntoSmart` R2 { x = 1.0 }+    , "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R3 { a = {=}, b = {=} }"+        `shouldMarshalIntoSmart` R3 { a = (), b = () }+    , "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R4 { x = 1.0, y = 2.0 }"+        `shouldMarshalIntoSmart` R4 { x = 1.0, y = 2.0 }++    , "< P0 | P1 : { _1 : {} } | P2 : { _1 : Double } | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P0"+        `shouldMarshalIntoWrapped` P0+    , "< P0 | P1 : { _1 : {} } | P2 : { _1 : Double } | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P1 { _1 = {=} }"+        `shouldMarshalIntoWrapped` P1 ()+    , "< P0 | P1 : { _1 : {} } | P2 : { _1 : Double } | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P2 { _1 = 1.0 }"+        `shouldMarshalIntoWrapped` P2 1.0+    , "< P0 | P1 : { _1 : {} } | P2 : { _1 : Double } | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P3 { _1 = {=}, _2 = {=} }"+        `shouldMarshalIntoWrapped` P3 () ()+    , "< P0 | P1 : { _1 : {} } | P2 : { _1 : Double } | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P4 { _1 = 1.0, _2 = 2.0 }"+        `shouldMarshalIntoWrapped` P4 1.0 2.0++    , "< P0 | P1 | P2 : Double | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P0"+        `shouldMarshalIntoSmart` P0+    , "< P0 | P1 | P2 : Double | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P1"+        `shouldMarshalIntoSmart` P1 ()+    , "< P0 | P1 | P2 : Double | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P2 1.0"+        `shouldMarshalIntoSmart` P2 1.0+    , "< P0 | P1 | P2 : Double | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P3 { _1 = {=}, _2 = {=} }"+        `shouldMarshalIntoSmart` P3 () ()+    , "< P0 | P1 | P2 : Double | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P4 { _1 = 1.0, _2 = 2.0 }"+        `shouldMarshalIntoSmart` P4 1.0 2.0+     , N0 True-        `shouldInjectInto`+        `shouldEmbedAsWrapped`         "(< N0 : { _1 : Bool } | N1 : { _1 : Natural } | N2 : { _1 : Text } >).N0 { _1 = True }"     , N1 5-        `shouldInjectInto`+        `shouldEmbedAsWrapped`         "(< N0 : { _1 : Bool } | N1 : { _1 : Natural } | N2 : { _1 : Text } >).N1 { _1 = 5 }"     , N2 "ABC"-        `shouldInjectInto`+        `shouldEmbedAsWrapped`         "(< N0 : { _1 : Bool } | N1 : { _1 : Natural } | N2 : { _1 : Text } >).N2 { _1 = \"ABC\" }" -    , E0 `shouldInjectInto` "< E0 | E1 | E2 >.E0"-    , E1 `shouldInjectInto` "< E0 | E1 | E2 >.E1"-    , E2 `shouldInjectInto` "< E0 | E1 | E2 >.E2"+    , N0 True+        `shouldEmbedAsSmart`+        "(< N0 : Bool | N1 : Natural | N2 : Text >).N0 True"+    , N1 5+        `shouldEmbedAsSmart`+        "(< N0 : Bool | N1 : Natural | N2 : Text >).N1 5"+    , N2 "ABC"+        `shouldEmbedAsSmart`+        "(< N0 : Bool | N1 : Natural | N2 : Text >).N2 \"ABC\"" -    , M0 True `shouldInjectInto` "(< M0 : { _1 : Bool } | M1 | M2 : { _1 : {} } >).M0 { _1 = True }"-    , M1 `shouldInjectInto` "(< M0 : { _1 : Bool } | M1 | M2 : { _1 : {} } >).M1"-    , M2 () `shouldInjectInto` "(< M0 : { _1 : Bool } | M1 | M2 : { _1 : {} } >).M2 { _1 = {=} }"+    , E0 `shouldEmbedAsWrapped` "< E0 | E1 | E2 >.E0"+    , E1 `shouldEmbedAsWrapped` "< E0 | E1 | E2 >.E1"+    , E2 `shouldEmbedAsWrapped` "< E0 | E1 | E2 >.E2"++    , R0 `shouldEmbedAsWrapped` "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R0"+    , R1 { a = () } `shouldEmbedAsWrapped` "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R1 { a = {=} }"+    , R2 { x = 1.0 } `shouldEmbedAsWrapped` "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R2 { x = 1.0}"+    , R3 { a = (), b = () } `shouldEmbedAsWrapped` "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R3 { a = {=}, b = {=} }"+    , R4 { x = 1.0, y = 2.0 } `shouldEmbedAsWrapped` "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R4 { x = 1.0, y = 2.0 }"++    , R0 `shouldEmbedAsSmart` "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R0"+    , R1 { a = () } `shouldEmbedAsSmart` "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R1 { a = {=} }"+    , R2 { x = 1.0 } `shouldEmbedAsSmart` "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R2 { x = 1.0}"+    , R3 { a = (), b = () } `shouldEmbedAsSmart` "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R3 { a = {=}, b = {=} }"+    , R4 { x = 1.0, y = 2.0 } `shouldEmbedAsSmart` "< R0 | R1 : { a : {} } | R2 : { x : Double } | R3 : { a : {}, b : {} } | R4 : { x : Double, y : Double } >.R4 { x = 1.0, y = 2.0 }"++    , P0 `shouldEmbedAsWrapped` "< P0 | P1 : { _1 : {} } | P2 : { _1 : Double } | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P0"+    , P1 () `shouldEmbedAsWrapped` "< P0 | P1 : { _1 : {} } | P2 : { _1 : Double } | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P1 { _1 = {=} }"+    , P2 1.0 `shouldEmbedAsWrapped` "< P0 | P1 : { _1 : {} } | P2 : { _1 : Double } | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P2 { _1 = 1.0 }"+    , P3 () () `shouldEmbedAsWrapped` "< P0 | P1 : { _1 : {} } | P2 : { _1 : Double } | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P3 { _1 = {=}, _2 = {=} }"+    , P4 1.0 2.0 `shouldEmbedAsWrapped` "< P0 | P1 : { _1 : {} } | P2 : { _1 : Double } | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P4 { _1 = 1.0, _2 = 2.0 }"++    , P0 `shouldEmbedAsSmart` "< P0 | P1 | P2 : Double | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P0"+    , P1 () `shouldEmbedAsSmart` "< P0 | P1 | P2 : Double | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P1"+    , P2 1.0 `shouldEmbedAsSmart` "< P0 | P1 | P2 : Double | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P2 1.0"+    , P3 () () `shouldEmbedAsSmart` "< P0 | P1 | P2 : Double | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P3 { _1 = {=}, _2 = {=} }"+    , P4 1.0 2.0 `shouldEmbedAsSmart` "< P0 | P1 | P2 : Double | P3 : { _1 : {}, _2 : {} } | P4 : { _1 : Double, _2 : Double } >.P4 { _1 = 1.0, _2 = 2.0 }"     ]   where-    code `shouldPassThrough` values = testCase "Pass through" $ do-        f <- Dhall.input Dhall.auto code+    smartOptions =+        Dhall.defaultInterpretOptions+            { Dhall.singletonConstructors = Dhall.Smart } +    wrappedOptions =+        Dhall.defaultInterpretOptions+            { Dhall.singletonConstructors = Dhall.Wrapped }++    functionWithOptions+      :: ( Generic a+         , Dhall.GenericToDhall (Rep a)+         , Generic b+         , Dhall.GenericFromDhall b (Rep b)+         )+      => Dhall.InterpretOptions -> Dhall.Decoder (a -> b)+    functionWithOptions options =+      Dhall.function (Dhall.genericToDhallWith options) (Dhall.genericAutoWith options)++    code `shouldPassThroughWrapped` values = testCase "Pass through" $ do+        f <- Dhall.input (functionWithOptions wrappedOptions) code+         values @=? map f values -    code `shouldMarshalInto` expectedValue = testCase "Marshal" $ do-        actualValue <- Dhall.input Dhall.auto code+    code `shouldPassThroughSmart` values = testCase "Pass through" $ do+        f <- Dhall.input (functionWithOptions smartOptions) code++        values @=? map f values++    code `shouldMarshalIntoWrapped` expectedValue = testCase "Marshal" $ do+        actualValue <- Dhall.input (Dhall.genericAutoWith wrappedOptions) code+         expectedValue @=? actualValue -    value `shouldInjectInto` expectedCode = testCase "Inject" $ do+    code `shouldMarshalIntoSmart` expectedValue = testCase "Marshal" $ do+        actualValue <- Dhall.input (Dhall.genericAutoWith smartOptions) code++        expectedValue @=? actualValue++    value `shouldEmbedAsWrapped` expectedCode = testCase "ToDhall" $ do         parsedExpression <- Dhall.Core.throws (Dhall.Parser.exprFromText "(test)" expectedCode)          resolvedExpression <- Dhall.Import.assertNoImports parsedExpression -        Dhall.Core.denote resolvedExpression @=? Dhall.embed Dhall.inject value+        Dhall.Core.denote resolvedExpression @=? Dhall.embed (Dhall.genericToDhallWith wrappedOptions) value++    value `shouldEmbedAsSmart` expectedCode = testCase "ToDhall" $ do+        parsedExpression <- Dhall.Core.throws (Dhall.Parser.exprFromText "(test)" expectedCode)++        resolvedExpression <- Dhall.Import.assertNoImports parsedExpression++        Dhall.Core.denote resolvedExpression @=? Dhall.embed (Dhall.genericToDhallWith smartOptions) value++shouldConvertDhallToHaskellCorrectly :: TestTree+shouldConvertDhallToHaskellCorrectly =+    testGroup+        "Marshall Dhall code to Haskell"+        [ "True" `correspondsTo` True+        , "False" `correspondsTo` False+        , "2" `correspondsTo` (2 :: Natural)+        , "+2" `correspondsTo` (2 :: Integer)+        , "2.0" `correspondsTo` (2.0 :: Double)+        , "2.0" `correspondsTo` (2.0 :: Scientific)+        , "\"ABC\"" `correspondsTo` ("ABC" :: Data.Text.Text)+        , "\"ABC\"" `correspondsTo` ("ABC" :: Data.Text.Lazy.Text)+        , "\"ABC\"" `correspondsTo` ("ABC" :: String)+        , "Some 2" `correspondsTo` (Just 2 :: Maybe Natural)+        , "None Natural" `correspondsTo` (Nothing :: Maybe Natural)+        , "[ 2, 3, 5 ]" `correspondsTo` ([ 2, 3, 5 ] :: Seq Natural)+        , "[ 2, 3, 5 ]" `correspondsTo` ([ 2, 3, 5 ] :: [Natural])+        , "[ 2, 3, 5 ]" `correspondsTo` ([ 2, 3, 5 ] :: Vector Natural)+        , "[] : List Natural" `correspondsTo` ([] :: [Natural])+        , "{=}" `correspondsTo` ()+        , "{ _1 = True, _2 = {=} }" `correspondsTo` (True, ())+        ]+  where+    correspondsTo :: (Eq a, FromDhall a, Show a) => Text -> a -> TestTree+    dhallCode `correspondsTo` expectedHaskellValue =+      testCase "Marshall Dhall code to Haskell" $ do+          actualHaskellValue <- Dhall.input Dhall.auto dhallCode++          expectedHaskellValue @=? actualHaskellValue++shouldConvertHaskellToDhallCorrectly :: TestTree+shouldConvertHaskellToDhallCorrectly =+    testGroup+        "Marshall Haskell to Dhall code"+        [ "True" `correspondsTo` True+        , "False" `correspondsTo` False+        , "2" `correspondsTo` (2 :: Natural)+        , "+2" `correspondsTo` (2 :: Integer)+        , "2.0" `correspondsTo` (2.0 :: Double)+        , "2.0" `correspondsTo` (2.0 :: Scientific)+        , "\"ABC\"" `correspondsTo` ("ABC" :: Data.Text.Text)+        , "\"ABC\"" `correspondsTo` ("ABC" :: Data.Text.Lazy.Text)+        , "\"ABC\"" `correspondsTo` ("ABC" :: String)+        , "Some 2" `correspondsTo` (Just 2 :: Maybe Natural)+        , "None Natural" `correspondsTo` (Nothing :: Maybe Natural)+        , "[ 2, 3, 5 ]" `correspondsTo` ([ 2, 3, 5 ] :: Seq Natural)+        , "[ 2, 3, 5 ]" `correspondsTo` ([ 2, 3, 5 ] :: [Natural])+        , "[ 2, 3, 5 ]" `correspondsTo` ([ 2, 3, 5 ] :: Vector Natural)+        , "[] : List Natural" `correspondsTo` ([] :: [Natural])+        , "{=}" `correspondsTo` ()+        , "{ _1 = True, _2 = {=} }" `correspondsTo` (True, ())+        ]+  where+    correspondsTo :: ToDhall a => Text -> a -> TestTree+    expectedDhallCode `correspondsTo` haskellValue =+        testCase "Marshall Haskell to Dhall code" $ do+            let actualDhallCode =+                    Dhall.Core.pretty (Dhall.embed Dhall.inject haskellValue)++            expectedDhallCode @=? actualDhallCode++-- https://github.com/dhall-lang/dhall-haskell/issues/1711+data Issue1711+  = A Bad+  | B+  | C+  | D+  deriving (Generic, Show, FromDhall)++newtype Bad = Bad Text+  deriving (Show)++issue1711Msg :: Text+issue1711Msg = "Issue 1711"++instance FromDhall Bad where+  autoWith _ =+    Dhall.Decoder+      (const (Dhall.extractError issue1711Msg))+      (Dhall.expected Dhall.strictText)++type DhallExtractErrors = Dhall.ExtractErrors Dhall.Parser.Src Void++-- https://github.com/dhall-lang/dhall-haskell/issues/1711+shouldShowCorrectErrorForInvalidDecoderInUnion :: TestTree+shouldShowCorrectErrorForInvalidDecoderInUnion =+  testCase "Correct error is thrown for invalid decoder in union" $ do+    let value = "< B | D | C | A : Text >.A \"\""++    inputEx :: Either DhallExtractErrors Issue1711 <- try (Dhall.input Dhall.auto value)++    let expectedMsg = issue1711Msg++    let assertMsg = "The exception message did not match the expected output"++    case inputEx of+      Left (Dhall.DhallErrors errs) -> case errs of+        (err :| []) -> case err of+          Dhall.TypeMismatch {} -> fail "The extraction using an invalid decoder failed with a type mismatch"+          Dhall.ExpectedTypeError _ -> fail "An error occurred while determining the expected Dhall type"+          Dhall.ExtractError extractError -> assertEqual assertMsg expectedMsg extractError+        _ -> fail "The extraction using an invalid decoder failed with multiple errors"+      Right _ -> fail "The extraction using an invalid decoder succeeded"
+ tests/Dhall/Test/Diff.hs view
@@ -0,0 +1,55 @@+{-# LANGUAGE OverloadedStrings #-}++module Dhall.Test.Diff where++import Data.Text  (Text)+import Test.Tasty (TestTree)++import qualified Data.Text                 as Text+import qualified Data.Text.IO              as Text.IO+import qualified Dhall.Core                as Core+import qualified Dhall.Diff                as Diff+import qualified Dhall.Parser              as Parser+import qualified Dhall.Pretty+import qualified Dhall.Test.Util           as Test.Util+import qualified Prettyprinter.Render.Text as Pretty.Text+import qualified Test.Tasty                as Tasty+import qualified Test.Tasty.HUnit          as Tasty.HUnit+import qualified Turtle++diffDirectory :: FilePath+diffDirectory = "./tests/diff"++getTests :: IO TestTree+getTests = do+    diffTests <- Test.Util.discover (Turtle.chars <* "A.dhall") diffTest (Turtle.lstree diffDirectory)++    let testTree = Tasty.testGroup "diff tests" [ diffTests ]++    return testTree++diffTest :: Text -> TestTree+diffTest prefix =+    Tasty.HUnit.testCase (Text.unpack prefix) $ do+        let leftFile  = Text.unpack (prefix <> "A.dhall")+        let rightFile = Text.unpack (prefix <> "B.dhall")+        let diffFile  = Text.unpack (prefix <> ".txt")++        let toInput file = do+                text <- Text.IO.readFile file+                Core.throws (Parser.exprFromText mempty text)++        leftInput  <- toInput leftFile+        rightInput <- toInput rightFile++        expectedDiffText <- Text.IO.readFile diffFile++        let actualDiffDocument =+                Diff.doc (Diff.diffNormalized leftInput rightInput) <> "\n"++        let actualDiffText = Pretty.Text.renderStrict+                    (Dhall.Pretty.layout actualDiffDocument)++        let message = "The diffed expressions did not match the expected output"++        Tasty.HUnit.assertEqual message expectedDiffText actualDiffText
+ tests/Dhall/Test/DirectoryTree.hs view
@@ -0,0 +1,149 @@+{-# LANGUAGE CPP               #-}+{-# LANGUAGE OverloadedLists   #-}+{-# LANGUAGE OverloadedStrings #-}++module Dhall.Test.DirectoryTree (tests) where++import Control.Monad+import Data.Either            (partitionEithers)+import Data.Either.Validation+import Dhall.DirectoryTree+import Lens.Micro             (set)+import System.FilePath        ((</>))+import Test.Tasty+import Test.Tasty.HUnit++import qualified Data.List+import qualified Data.Text.IO+import qualified Dhall+import qualified Dhall.Core+import qualified System.Directory         as Directory+import qualified System.FilePath          as FilePath+import qualified System.PosixCompat.Files as Files++tests :: TestTree+tests = testGroup "to-directory-tree"+    [ testGroup "fixpointed"+        [ fixpointedType+        , fixpointedEmpty+        , fixpointedSimple+        , fixpointedAllowPathSeparators+#ifndef mingw32_HOST_OS+        , fixpointedPermissions+        , fixpointedUserGroup+#endif+        ]+    ]++fixpointedType :: TestTree+fixpointedType = testCase "Type is as expected" $ do+    let file = "./tests/to-directory-tree/type.dhall"+    ref <- Dhall.inputExpr file+    expected' <- case directoryTreeType of+        Failure e -> assertFailure $ show e+        Success expr -> return expr+    assertBool "Type mismatch" $ expected' `Dhall.Core.judgmentallyEqual` ref++fixpointedEmpty :: TestTree+fixpointedEmpty = testCase "empty" $ do+    let outDir = "./tests/to-directory-tree/fixpoint-empty.out"+        path = "./tests/to-directory-tree/fixpoint-empty.dhall"+    entries <- runDirectoryTree False outDir path+    entries @?= [Directory outDir]++fixpointedSimple :: TestTree+fixpointedSimple = testCase "simple" $ do+    let outDir = "./tests/to-directory-tree/fixpoint-simple.out"+        path = "./tests/to-directory-tree/fixpoint-simple.dhall"+    entries <- runDirectoryTree False outDir path+    entries @?= Data.List.sort+        [ Directory outDir+        , File $ outDir </> "file"+        , Directory $ outDir </> "directory"+        ]++fixpointedAllowPathSeparators :: TestTree+fixpointedAllowPathSeparators = testCase "allow-path-separators" $ do+    let outDir = "./tests/to-directory-tree/fixpoint-allow-path-separators.out"+        path = "./tests/to-directory-tree/fixpoint-allow-path-separators.dhall"+    entries <- runDirectoryTree True outDir path+    entries @?= Data.List.sort+        [ Directory outDir+        , Directory $ outDir </> "non-existent-1"+        , File $ outDir </> "non-existent-1" </> "file"+        , Directory $ outDir </> "non-existent-2"+        , Directory $ outDir </> "non-existent-2" </> "directory"+        ]++{-+This test is disabled on Windows as it fails due to limitations of the :+    expected: 448+    but got: 438+-}+fixpointedPermissions :: TestTree+fixpointedPermissions = testCase "permissions" $ do+    let outDir = "./tests/to-directory-tree/fixpoint-permissions.out"+        path = "./tests/to-directory-tree/fixpoint-permissions.dhall"+    entries <- runDirectoryTree False outDir path+    entries @?=+        [ Directory outDir+        , File $ outDir </> "file"+        ]+    s <- Files.getFileStatus $ outDir </> "file"+    let mode = Files.fileMode s `Files.intersectFileModes` Files.accessModes+    prettyFileMode mode @?= prettyFileMode Files.ownerModes++fixpointedUserGroup :: TestTree+fixpointedUserGroup = testCase "user and group" $ do+    let file = "./tests/to-directory-tree/fixpoint-usergroup.dhall"+    expr <- Dhall.inputExpr file+    entries <- decodeDirectoryTree expr+    entries @?=+        [ TextFileEntry $ Entry+            { entryName = "ids"+            , entryContent = ""+            , entryUser = Just (UserId 0)+            , entryGroup = Just (GroupId 0)+            , entryMode = Nothing+            }+        , TextFileEntry $ Entry+            { entryName = "names"+            , entryContent = ""+            , entryUser = Just (UserName "user")+            , entryGroup = Just (GroupName "group")+            , entryMode = Nothing+            }+        ]++runDirectoryTree :: Bool -> FilePath -> FilePath -> IO [WalkEntry]+runDirectoryTree allowSeparators outDir path = do+    doesOutDirExist <- Directory.doesDirectoryExist outDir+    when doesOutDirExist $+        Directory.removeDirectoryRecursive outDir+    Directory.createDirectoryIfMissing True outDir++    text <- Data.Text.IO.readFile path+    let inputSettings+            = set Dhall.rootDirectory (FilePath.takeDirectory path)+            . set Dhall.sourceName path+            $ Dhall.defaultInputSettings+    expr <- Dhall.inputExprWithSettings inputSettings text++    toDirectoryTree allowSeparators outDir $ Dhall.Core.denote expr++    Data.List.sort <$> walkFsTree outDir++data WalkEntry+    = Directory FilePath+    | File FilePath+    deriving (Eq, Ord, Show)++walkFsTree :: FilePath -> IO [WalkEntry]+walkFsTree dir = do+    entries <- Directory.listDirectory dir+    (ds, fs) <- fmap partitionEithers $ forM entries $ \path -> do+        let path' = dir </> path+        isDirectory <- Directory.doesDirectoryExist path'+        return $ if isDirectory then Left path' else Right (File path')+    entries' <- traverse walkFsTree ds+    return $ Directory dir : fs <> concat entries'
tests/Dhall/Test/Format.hs view
@@ -2,22 +2,21 @@  module Dhall.Test.Format where -import Data.Monoid (mempty, (<>))-import Data.Text (Text)-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@@ -27,7 +26,7 @@              let skip = [ "./tests/format/asciiA.dhall" ] -            Monad.guard (path `notElem` skip)+            path `Test.Util.pathNotIn` skip              return path @@ -43,23 +42,26 @@      return testTree -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+format :: CharacterSet -> (Header, Core.Expr Parser.Src Core.Import) -> Text+format characterSet (Header header, expr) =+    let doc =  Doc.pretty header+            <> Pretty.prettyCharacterSet characterSet expr+            <> "\n" -        expr <- Core.throws (Parser.exprFromText mempty inputText)+        docStream = Pretty.layout doc+    in+        Doc.Render.Text.renderStrict docStream -        let doc        = Pretty.prettyCharacterSet characterSet  expr-        let docStream  = Doc.layoutSmart Pretty.layoutOpts doc-        let actualText = Doc.Render.Text.renderStrict docStream+formatTest :: CharacterSet -> Text -> TestTree+formatTest characterSet prefix =+    let inputFile  = Text.unpack (prefix <> "A.dhall")+        outputFile = Text.unpack (prefix <> "B.dhall") -        expectedText <- Text.IO.readFile outputFile+        action = do+            inputText <- Text.IO.readFile inputFile -        let message =-                "The formatted expression did not match the expected output"+            headerAndExpr <- Core.throws (Parser.exprAndHeaderFromText mempty inputText) -        Tasty.HUnit.assertEqual message expectedText actualText+            return (format characterSet headerAndExpr)+    in+        Tasty.Silver.goldenVsAction (Text.unpack prefix) outputFile action id
+ tests/Dhall/Test/Freeze.hs view
@@ -0,0 +1,59 @@+{-# LANGUAGE OverloadedStrings #-}++module Dhall.Test.Freeze where++import Data.Text    (Text)+import Dhall.Freeze (Intent (..), Scope (..))+import Test.Tasty   (TestTree)++import qualified Data.Text        as Text+import qualified Data.Text.IO     as Text.IO+import qualified Dhall.Core       as Core+import qualified Dhall.Freeze     as Freeze+import qualified Dhall.Parser     as Parser+import qualified Dhall.Test.Util  as Test.Util+import qualified Test.Tasty       as Tasty+import qualified Test.Tasty.HUnit as Tasty.HUnit+import qualified Turtle++freezeDirectoryCached :: FilePath+freezeDirectoryCached = "./tests/freeze/cached"++freezeDirectorySecure :: FilePath+freezeDirectorySecure = "./tests/freeze/secure"++getTests :: IO TestTree+getTests = do+    freezeCachedTests <- Test.Util.discover (Turtle.chars <* "A.dhall")+        (freezeTest freezeDirectoryCached Cache)+        (Turtle.lstree freezeDirectoryCached)+    freezeSecureTests <- Test.Util.discover (Turtle.chars <* "A.dhall")+        (freezeTest freezeDirectorySecure Secure)+        (Turtle.lstree freezeDirectorySecure)++    let testTree = Tasty.testGroup "freeze tests"+            [ Tasty.testGroup "cached" [freezeCachedTests]+            , Tasty.testGroup "secure" [freezeSecureTests]+            ]++    return testTree++freezeTest :: FilePath -> Intent -> Text -> TestTree+freezeTest dir intent prefix =+    Tasty.HUnit.testCase (Text.unpack prefix) $ do+        let inputFile  = Text.unpack (prefix <> "A.dhall")+        let outputFile = Text.unpack (prefix <> "B.dhall")++        inputText <- Text.IO.readFile inputFile++        parsedInput <- Core.throws (Parser.exprFromText mempty inputText)++        actualExpression <- Freeze.freezeExpression dir AllImports intent parsedInput++        let actualText = Core.pretty actualExpression <> "\n"++        expectedText <- Text.IO.readFile outputFile++        let message = "The linted expression did not match the expected output"++        Tasty.HUnit.assertEqual message expectedText actualText
tests/Dhall/Test/Import.hs view
@@ -1,16 +1,16 @@+{-# LANGUAGE CPP               #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeApplications  #-}  module Dhall.Test.Import where -import Control.Exception (catch)-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 Control.Exception (SomeException)+import Data.Text         (Text)+import Data.Void         (Void)+import System.FilePath   ((</>))+import Test.Tasty        (TestTree) +import qualified Control.Exception                as Exception import qualified Control.Monad.Trans.State.Strict as State import qualified Data.Text                        as Text import qualified Data.Text.IO                     as Text.IO@@ -19,19 +19,87 @@ import qualified Dhall.Parser                     as Parser import qualified Dhall.Test.Util                  as Test.Util import qualified System.FilePath                  as FilePath+import qualified System.IO.Temp                   as Temp import qualified Test.Tasty                       as Tasty import qualified Test.Tasty.HUnit                 as Tasty.HUnit import qualified Turtle +#if defined(WITH_HTTP) && defined(NETWORK_TESTS)+import qualified Network.HTTP.Client     as HTTP+import qualified Network.HTTP.Client.TLS as HTTP+#endif++ importDirectory :: FilePath importDirectory = "./dhall-lang/tests/import"  getTests :: IO TestTree getTests = do-    successTests <- Test.Util.discover (Turtle.chars <> "A.dhall") successTest (Turtle.lstree (importDirectory </> "success"))+    let flakyTests =+            [ -- This test is flaky, occasionally failing with:+              --+              --     Error: Remote host not found+              --+              --     URL: https://test.dhall-lang.org/Bool/package.dhall+              importDirectory </> "success/headerForwardingA.dhall"+            , importDirectory </> "success/unit/RemoteAsTextA.dhall"+            , importDirectory </> "success/unit/SimpleRemoteA.dhall"+            , importDirectory </> "success/unit/asLocation/RemoteChain1A.dhall"+            , importDirectory </> "success/unit/asLocation/RemoteChain2A.dhall"+            , importDirectory </> "success/unit/asLocation/RemoteChain3A.dhall"+            , importDirectory </> "success/unit/asLocation/RemoteChainMissingA.dhall" -    failureTests <- Test.Util.discover (Turtle.chars <> ".dhall") failureTest (Turtle.lstree (importDirectory </> "failure"))+              -- Skip all tests that reference httpbin.org to avoid clobbering+              -- their servers.  These should eventually be replaced by tests+              -- that depend on an equivalent endpoint on test.dhall-lang.org+              -- instead of httpbin.org.+            , importDirectory </> "failure/customHeadersUsingBoundVariable.dhall"+            , importDirectory </> "failure/originHeadersFromRemote.dhall"+            , importDirectory </> "failure/originHeadersFromRemoteENV.dhall"+            , importDirectory </> "success/customHeadersA.dhall"+            , importDirectory </> "success/noHeaderForwardingA.dhall"+            , importDirectory </> "success/success/originHeadersA.dhall"+            , importDirectory </> "success/originHeadersENV.dhall"+            , importDirectory </> "success/originHeadersImportA.dhall"+            , importDirectory </> "success/originHeadersImportENV.dhall"+            , importDirectory </> "success/originHeadersImportFromEnvA.dhall"+            , importDirectory </> "success/originHeadersImportFromEnvENV.dhall"+            , importDirectory </> "success/originHeadersOverrideA.dhall"+            , importDirectory </> "success/originHeadersOverrideENV.dhall"+            ] +    successTests <- Test.Util.discover (Turtle.chars <* "A.dhall") successTest (do+        path <- Turtle.lstree (importDirectory </> "success")++        path `Test.Util.pathNotIn` flakyTests++        return path )++    failureTests <- Test.Util.discover (Turtle.chars <* ".dhall") failureTest (do+        path <- Turtle.lstree (importDirectory </> "failure")++        let expectedSuccesses =+                [ importDirectory </> "failure/unit/DontRecoverCycle.dhall"+                , importDirectory </> "failure/unit/DontRecoverTypeError.dhall"+#if !(defined(WITH_HTTP) && defined(NETWORK_TESTS))+                -- We attempt to simulate test.dhall-lang.org, but even so+                -- some tests unexpectedly succeed due to the inadequacy of+                -- the simulation+                , importDirectory </> "failure/unit/cors/OnlySelf.dhall"+                , importDirectory </> "failure/unit/cors/OnlyOther.dhall"+                , importDirectory </> "failure/unit/cors/Null.dhall"+                , importDirectory </> "failure/unit/cors/TwoHops.dhall"+                , importDirectory </> "failure/unit/cors/Empty.dhall"+                , importDirectory </> "failure/unit/cors/NoCORS.dhall"+                , importDirectory </> "failure/originHeadersFromRemote.dhall"+#endif+                ]++        path `Test.Util.pathNotIn` expectedSuccesses+        "ENV.dhall" `Test.Util.pathNotSuffixOf` path++        return path )+     let testTree =             Tasty.testGroup "import tests"                 [ successTests@@ -41,32 +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") -    Tasty.HUnit.testCase pathString (do+    let directoryString = FilePath.takeDirectory inputPath -        text <- Text.IO.readFile pathString+    let expectedFailures =+            [+              -- Importing relative to the home directory works, but I'm too+              -- lazy to mock the home directory for testing purposes+              importDirectory </> "success/unit/ImportRelativeToHome"+#if !(defined(WITH_HTTP) && defined(NETWORK_TESTS))+            , importDirectory </> "success/originHeadersImportFromEnv"+            , importDirectory </> "success/originHeadersImport"+            , importDirectory </> "success/originHeadersOverride"+            , importDirectory </> "success/unit/asLocation/RemoteChainEnv"+#endif+            ] +    Test.Util.testCase prefix expectedFailures (do++        text <- Text.IO.readFile inputPath++        expectedText <- Text.IO.readFile expectedPath+         actualExpr <- Core.throws (Parser.exprFromText mempty text) -        _ <- State.evalStateT (Import.loadWith actualExpr) (Import.emptyStatus directoryString)+        expectedExpr <- Core.throws (Parser.exprFromText mempty expectedText) -        return () )+        let originalCache = "dhall-lang/tests/import/cache" +#if defined(WITH_HTTP) && defined(NETWORK_TESTS)+        let httpManager =+                HTTP.newManager+                    HTTP.tlsManagerSettings+                        { HTTP.managerResponseTimeout = HTTP.responseTimeoutMicro (120 * 1000 * 1000) }++        let status =+                Import.makeEmptyStatus+                    httpManager+                    (pure Import.envOriginHeaders)+                    directoryString+#else+        let status = Import.emptyStatus directoryString+#endif++        let load =+                State.evalStateT+                    (Test.Util.loadWith actualExpr)+                    status++        let usesCache = [ "hashFromCache"+                        , "unit/asLocation/Hash"+                        , "unit/IgnorePoisonedCache"+                        , "unit/DontCacheIfHash"+                        ]++        let endsIn path' =+                not (null (Turtle.match (Turtle.ends path') (Test.Util.toDhallPath prefix)))++        let buildNewCache = do+                tempdir <- Turtle.managed (Temp.withSystemTempDirectory "dhall-cache")+                Turtle.liftIO (Turtle.cptree originalCache tempdir)+                return tempdir++        let cacheSetup =+                if any endsIn usesCache+                    then do+                        cacheDir <- buildNewCache++                        let set = do+                                m <- Turtle.need "XDG_CACHE_HOME"++                                Turtle.export "XDG_CACHE_HOME" (Turtle.format Turtle.fp cacheDir)++                                return m++                        let reset Nothing = do+                                Turtle.unset "XDG_CACHE_HOME"+                            reset (Just x) = do+                                Turtle.export "XDG_CACHE_HOME" x++                        _ <- Turtle.managed (Exception.bracket set reset)+                        return ()+                else pure ()++        let setup = cacheSetup >> Test.Util.managedTestEnvironment prefix++        let resolve = Turtle.with setup (const load)++        let handler :: SomeException -> IO (Core.Expr Parser.Src Void)+            handler exception = Tasty.HUnit.assertFailure (show exception)++        actualResolved <- Exception.handle handler resolve++        expectedResolved <- Import.assertNoImports expectedExpr++        let actual = Core.normalize actualResolved :: Core.Expr Void Void++        let expected = Core.normalize expectedResolved :: Core.Expr Void Void++        let message =+                "The imported expression did not match the expected output"++        Tasty.HUnit.assertEqual message expected actual)+ failureTest :: Text -> TestTree-failureTest 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 -        catch-          (do _ <- Import.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,22 +2,21 @@  module Dhall.Test.Lint where -import Data.Monoid (mempty, (<>))-import Data.Text (Text)-import Dhall.Core (Expr, Import)-import Dhall.TypeCheck (X)-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 Dhall.Core       as Core-import qualified Dhall.Lint       as Lint-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.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@@ -25,12 +24,22 @@  getTests :: IO TestTree getTests = do-    formatTests <- Test.Util.discover (Turtle.chars <* "A.dhall") lintTest (Turtle.lstree lintDirectory)+    lintTests <- Test.Util.discover (Turtle.chars <* "A.dhall") lintTest (Turtle.lstree lintDirectory) -    let testTree = Tasty.testGroup "format tests" [ formatTests ]+    let testTree = Tasty.testGroup "lint tests" [ lintTests ]      return testTree +format :: Header -> Core.Expr Parser.Src Core.Import -> Text+format (Header header) expr =+    let doc =  Doc.pretty header+            <> Pretty.prettyCharacterSet Pretty.Unicode expr+            <> "\n"++        docStream = Pretty.layout doc+    in+        Doc.Render.Text.renderStrict docStream+ lintTest :: Text -> TestTree lintTest prefix =     Tasty.HUnit.testCase (Text.unpack prefix) $ do@@ -39,18 +48,14 @@          inputText <- Text.IO.readFile inputFile -        parsedInput <- Core.throws (Parser.exprFromText mempty inputText)--        let actualExpression :: Expr X Import-            actualExpression = Core.denote (Lint.lint parsedInput)+        (header, parsedInput) <- Core.throws (Parser.exprAndHeaderFromText mempty inputText) -        outputText <- Text.IO.readFile outputFile+        let actualExpression = Lint.lint parsedInput -        parsedOutput <- Core.throws (Parser.exprFromText mempty outputText)+        let actualText = format header actualExpression -        let expectedExpression :: Expr X Import-            expectedExpression = Core.denote parsedOutput+        expectedText <- Text.IO.readFile outputFile          let message = "The linted expression did not match the expected output" -        Tasty.HUnit.assertEqual message expectedExpression actualExpression+        Tasty.HUnit.assertEqual message expectedText actualText
tests/Dhall/Test/Main.hs view
@@ -1,18 +1,29 @@+{-# LANGUAGE CPP #-} module Main where  import System.FilePath ((</>)) import Test.Tasty      (TestTree)  import qualified Dhall.Test.Dhall+import qualified Dhall.Test.Diff+import qualified Dhall.Test.DirectoryTree import qualified Dhall.Test.Format+import qualified Dhall.Test.Freeze import qualified Dhall.Test.Import import qualified Dhall.Test.Lint import qualified Dhall.Test.Normalization+import qualified Dhall.Test.Package import qualified Dhall.Test.Parser import qualified Dhall.Test.QuickCheck import qualified Dhall.Test.Regression+import qualified Dhall.Test.Schemas+import qualified Dhall.Test.SemanticHash+#ifndef CROSS+import qualified Dhall.Test.TH+#endif+import qualified Dhall.Test.Tags import qualified Dhall.Test.Tutorial-import qualified Dhall.Test.TypeCheck+import qualified Dhall.Test.TypeInference import qualified GHC.IO.Encoding import qualified System.Directory import qualified System.Environment@@ -27,24 +38,44 @@      formattingTests <- Dhall.Test.Format.getTests -    typecheckingTests <- Dhall.Test.TypeCheck.getTests+    typeinferenceTests <- Dhall.Test.TypeInference.getTests      importingTests <- Dhall.Test.Import.getTests      lintTests <- Dhall.Test.Lint.getTests +    tagsTests <- Dhall.Test.Tags.getTests++    diffTests <- Dhall.Test.Diff.getTests++    semanticHashTests <- Dhall.Test.SemanticHash.getTests++    freezeTests <- Dhall.Test.Freeze.getTests++    schemaTests <- Dhall.Test.Schemas.getTests+     let testTree =             Test.Tasty.testGroup "Dhall Tests"                 [ normalizationTests                 , parsingTests                 , importingTests-                , typecheckingTests+                , typeinferenceTests                 , formattingTests                 , lintTests+                , diffTests+                , semanticHashTests+                , tagsTests+                , freezeTests+                , schemaTests+                , Dhall.Test.DirectoryTree.tests                 , Dhall.Test.Regression.tests                 , Dhall.Test.Tutorial.tests                 , Dhall.Test.QuickCheck.tests                 , Dhall.Test.Dhall.tests+#ifndef CROSS+                , Dhall.Test.TH.tests+#endif+                , Dhall.Test.Package.tests                 ]      return testTree@@ -56,6 +87,12 @@     pwd <- System.Directory.getCurrentDirectory      System.Environment.setEnv "XDG_CACHE_HOME" (pwd </> ".cache")++    System.Environment.setEnv "DHALL_TEST_VAR" "6 * 7"++    -- Make test failures easier to find by eliding the successes.+    -- https://github.com/feuerbach/tasty/issues/273#issuecomment-657054281+    System.Environment.setEnv "TASTY_HIDE_SUCCESSES" "true"      allTests <- getAllTests 
tests/Dhall/Test/Normalization.hs view
@@ -2,15 +2,12 @@  module Dhall.Test.Normalization where -import Data.Monoid ((<>))-import Data.Text (Text)-import Dhall.Core (Expr(..), Var(..), throws)-import Dhall.TypeCheck (X)-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 Control.Monad    as Monad import qualified Data.Text        as Text import qualified Data.Text.IO     as Text.IO import qualified Dhall.Context    as Context@@ -19,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@@ -26,43 +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 = do-            path <- Turtle.lstree "./dhall-lang/tests/normalization/success/unit"--            let skip =-                    [ normalizationDirectory </> "unit/EmptyAlternativeA.dhall"-                    -- https://github.com/dhall-lang/dhall-lang/issues/505-                    , normalizationDirectory </> "unit/OperatorTextConcatenateLhsEmptyA.dhall"-                    ]--            Monad.guard (path `notElem` skip)--            return path+    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                 ] @@ -80,7 +76,7 @@     let tyCtx =             Context.insert                 "min"-                (Pi "_" Natural (Pi "_" Natural Natural))+                (Pi mempty "_" Natural (Pi mempty "_" Natural Natural))                 Context.empty          valCtx e =@@ -98,7 +94,7 @@ nestedReduction = Tasty.HUnit.testCase "doubleReduction" $ do     minType        <- Context.insert "min"        <$> Test.Util.code "Natural → Natural → Natural"     fiveorlessType <- Context.insert "fiveorless" <$> Test.Util.code "Natural → Natural"-    wurbleType     <- Context.insert "wurble"     <$> Test.Util.code "Natural → Integer"+    wurbleType     <- Context.insert "wurble"     <$> Test.Util.code "Natural → Natural"      let tyCtx = minType . fiveorlessType . wurbleType $ Context.empty @@ -138,10 +134,10 @@          expectedResolved <- Import.assertNoImports expectedExpr -        let expectedNormalized = Core.denote expectedResolved :: Expr X X+        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 @@ -150,9 +146,11 @@ -} unitTest :: Text -> TestTree unitTest prefix = do+    let expectedFailures = []+     let prefixString = Text.unpack prefix -    Tasty.HUnit.testCase prefixString $ do+    Test.Util.testCase prefix expectedFailures $ do         let actualPath   = prefixString <> "A.dhall"         let expectedPath = prefixString <> "B.dhall" @@ -165,7 +163,7 @@          let actualNormalized =                 Core.alphaNormalize-                    (Core.normalize actualResolved :: Expr X X)+                    (Core.normalize actualResolved :: Expr Void Void)          expectedExpr <- throws (Parser.exprFromText mempty expectedCode) @@ -180,11 +178,15 @@         Tasty.HUnit.assertEqual message expectedNormalized actualNormalized  betaNormalizationTest :: Text -> TestTree-betaNormalizationTest prefix =-    Tasty.HUnit.testCase (Text.unpack prefix) $ do-        let actualCode   = Test.Util.toDhallPath (prefix <> "A.dhall")-        let expectedCode = Test.Util.toDhallPath (prefix <> "B.dhall")+betaNormalizationTest prefix = do+    let prefixString = Text.unpack prefix +    Tasty.HUnit.testCase prefixString $ do+        let actualCode = Test.Util.toDhallPath (prefix <> "A.dhall")++        let expectedPath = prefixString <> "B.dhall"+        expectedCode <- Text.IO.readFile expectedPath+         actualExpr <- throws (Parser.exprFromText mempty actualCode)          actualResolved <- Import.load actualExpr@@ -193,7 +195,7 @@          let actualNormalized =                 Core.alphaNormalize-                    (Core.normalize actualResolved :: Expr X X)+                    (Core.normalize actualResolved :: Expr Void Void)          expectedExpr <- throws (Parser.exprFromText mempty expectedCode) @@ -207,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,17 +2,18 @@  module Dhall.Test.Parser where -import Data.Text (Text)-import Dhall.Core (Expr, Import)-import Dhall.TypeCheck (X)-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 Codec.Serialise      as Serialise import qualified Control.Monad        as Monad+import qualified Data.Bifunctor       as Bifunctor+import qualified Data.ByteString      as ByteString import qualified Data.ByteString.Lazy as ByteString.Lazy import qualified Data.Text            as Text+import qualified Data.Text.Encoding   as Text.Encoding import qualified Data.Text.IO         as Text.IO import qualified Dhall.Binary         as Binary import qualified Dhall.Core           as Core@@ -20,6 +21,7 @@ import qualified Dhall.Test.Util      as Test.Util import qualified Test.Tasty           as Tasty import qualified Test.Tasty.HUnit     as Tasty.HUnit+import qualified Text.Printf          as Printf import qualified Turtle  parseDirectory :: FilePath@@ -30,116 +32,188 @@  getTests :: IO TestTree getTests = do-    let successFiles = do-            path <- Turtle.lstree (parseDirectory </> "success")--            let skip =-                    -- This is a bug created by a parsing performance-                    -- improvement-                    [ parseDirectory </> "success/unit/MergeParenAnnotationA.dhall"-                    ]--            Monad.guard (path `notElem` skip)--            return path+    let successFiles = Turtle.lstree (parseDirectory </> "success") -    successTests <- do+    successTests <-         Test.Util.discover (Turtle.chars <* "A.dhall") shouldParse successFiles -    let failureFiles = do-            path <- Turtle.lstree (parseDirectory </> "failure")--            let skip =-                    [ -- These two unexpected successes are due to not correctly-                      -- requiring non-empty whitespace after the `:` in a type-                      -- annotatoin-                      parseDirectory </> "failure/annotation.dhall"-                    , parseDirectory </> "failure/unit/ImportEnvWrongEscape.dhall"--                      -- Similarly, the implementation does not correctly-                      -- require a space between a function and its argument-                    , parseDirectory </> "failure/missingSpace.dhall"--                      -- 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/ListLitEmptyAnnotation.dhall"-                      -- The same performance improvements also broke the-                      -- precedence of parsing empty list literals-                    , parseDirectory </> "failure/unit/ListLitEmptyPrecedence.dhall"-                    ]--            Monad.guard (path `notElem` skip)--            return path+    let failureFiles = Turtle.lstree (parseDirectory </> "failure") -    failureTests <- do+    failureTests <-         Test.Util.discover (Turtle.chars <> ".dhall") shouldNotParse failureFiles -    let binaryDecodeFiles =+    let binaryDecodeSuccessFiles =             Turtle.lstree (binaryDecodeDirectory </> "success") -    binaryDecodeTests <- do-        Test.Util.discover (Turtle.chars <* "A.dhallb") shouldDecode binaryDecodeFiles+    binaryDecodeSuccessTests <-+        Test.Util.discover (Turtle.chars <* "A.dhallb") shouldDecode binaryDecodeSuccessFiles +    let binaryDecodeFailureFiles = Turtle.lstree (binaryDecodeDirectory </> "failure")++    binaryDecodeFailureTests <-+        Test.Util.discover (Turtle.chars <* ".dhallb") shouldNotDecode binaryDecodeFailureFiles+     let testTree =             Tasty.testGroup "parser tests"                 [ successTests                 , failureTests-                , binaryDecodeTests+                , internalTests+                , binaryDecodeSuccessTests+                , binaryDecodeFailureTests                 ]      return testTree +internalTests :: TestTree+internalTests =+    Tasty.testGroup "internal"+        [ notesInLetInLet ]++notesInLetInLet :: TestTree+notesInLetInLet =+    Tasty.HUnit.testCase "Notes in let-in-let" $ do+        let code = "let x = 0 let y = 1 in let z = 2 in x"++        expression <- Core.throws (Parser.exprFromText mempty code)++        let simplifyNotes = Bifunctor.first Parser.srcText++        let expected =+                (Note code+                  (Let+                    (Binding+                      (Just " ")+                      "x"+                      (Just " ")+                      Nothing+                      (Just " ")+                      (Note "0 " (Note "0" (NaturalLit 0)))+                    )+                    -- This 'Let' isn't wrapped in a 'Note'!+                    (Let+                      (Binding+                        (Just " ")+                        "y"+                        (Just " ")+                        Nothing+                        (Just " ")+                        (Note "1 " (Note "1" (NaturalLit 1)))+                      )+                      (Note "let z = 2 in x"+                        (Let+                          (Binding+                            (Just " ")+                            "z"+                            (Just " ")+                            Nothing+                            (Just " ")+                            (Note "2 " (Note "2" (NaturalLit 2)))+                          )+                          (Note "x" (Var (V "x" 0)))+                        )+                      )+                    )+                  )+                )++        let msg = "Unexpected parse result"++        Tasty.HUnit.assertEqual msg expected (simplifyNotes expression)+ shouldParse :: Text -> TestTree shouldParse path = do+    let expectedFailures = []+     let pathString = Text.unpack path -    Tasty.HUnit.testCase pathString $ do+    Test.Util.testCase path expectedFailures $ do         text <- Text.IO.readFile (pathString <> "A.dhall")          encoded <- ByteString.Lazy.readFile (pathString <> "B.dhallb") -        expression <- Core.throws (Parser.exprFromText mempty text)+        expression <- case Parser.exprFromText mempty text of+            Left  exception  -> Tasty.HUnit.assertFailure (show exception)+            Right expression -> return expression -        let term = Binary.encode expression+        let bytes = Binary.encodeExpression (Core.denote expression) -        let bytes = Serialise.serialise term+        let render =+                  concatMap (Printf.printf "%02x ")+                . ByteString.Lazy.unpack -        let message = "The expected CBOR representation doesn't match the actual one"-        Tasty.HUnit.assertEqual message encoded bytes+        Monad.unless (encoded == bytes) $ do+            let message = "The expected CBOR representation doesn't match the actual one\n"+                          ++ "expected: " ++ render encoded ++ "\n but got: " ++ render bytes+                          ++ "\n expr: " ++ show (Core.denote expression :: Expr Void Import) +            Tasty.HUnit.assertFailure message++ shouldNotParse :: Text -> TestTree shouldNotParse path = do+    let expectedFailures =+            [ parseDirectory </> "failure/spacing/LetNoSpace4.dhall"+            ]+     let pathString = Text.unpack path -    Tasty.HUnit.testCase pathString (do-        text <- Text.IO.readFile pathString+    Test.Util.testCase path expectedFailures (do+        bytes <- ByteString.readFile pathString -        case Parser.exprFromText mempty text of-            Left  _ -> return ()-            Right _ -> fail "Unexpected successful parser" )+        case Text.Encoding.decodeUtf8' bytes of+            Left _ -> return ()+            Right text ->+                case Parser.exprFromText mempty text of+                    Left  _ -> return ()+                    Right _ -> Tasty.HUnit.assertFailure "Unexpected successful parse" )  shouldDecode :: Text -> TestTree shouldDecode pathText = do+    let expectedFailures =+          [ {- Note that this test actually successfully decodes the value, but+               mistakenly decodes the value to `_` instead of `x`.  This is+               because the 55799 tag causes normal decoding to fail, so it falls+               back to treating the `"x"` as a version tag instead of a label.++               Either way, fixing 55799 decoding would cause this test to pass+               again.+            -}+            binaryDecodeDirectory </> "success/unit/SelfDescribeCBORX2"+          , binaryDecodeDirectory </> "success/unit/SelfDescribeCBORX3"+          ]+     let pathString = Text.unpack pathText -    Tasty.HUnit.testCase pathString (do+    Test.Util.testCase pathText expectedFailures (do         bytes <- ByteString.Lazy.readFile (pathString <> "A.dhallb") -        term <- Core.throws (Serialise.deserialiseOrFail bytes)--        decodedExpression <- Core.throws (Binary.decodeExpression term)+        decodedExpression <- case Binary.decodeExpression bytes of+            Left exception ->+                Tasty.HUnit.assertFailure (show exception)+            Right decodedExpression ->+                return decodedExpression          text <- Text.IO.readFile (pathString <> "B.dhall")          parsedExpression <- Core.throws (Parser.exprFromText mempty text) -        let strippedExpression :: Expr X Import+        let strippedExpression :: Expr Void Import             strippedExpression = Core.denote parsedExpression          let message =                 "The decoded expression didn't match the parsed expression" -        Tasty.HUnit.assertEqual message decodedExpression strippedExpression )+        Tasty.HUnit.assertEqual message strippedExpression decodedExpression )++shouldNotDecode :: Text -> TestTree+shouldNotDecode pathText = do+    let expectedFailures = []++    let pathString = Text.unpack pathText++    Test.Util.testCase pathText expectedFailures (do+        bytes <- ByteString.Lazy.readFile (pathString <> ".dhallb")++        case Binary.decodeExpression bytes :: Either Binary.DecodingFailure (Expr Void Import) of+            Left _ -> return ()+            Right _ -> Tasty.HUnit.assertFailure "Unexpected successful decode" )
tests/Dhall/Test/QuickCheck.hs view
@@ -1,63 +1,118 @@-{-# LANGUAGE OverloadedStrings  #-}-{-# LANGUAGE RecordWildCards    #-}-{-# LANGUAGE StandaloneDeriving #-}+-- TODO: update because we added ShowConstructor constructor to Expr in Dhall.Syntax +{-# LANGUAGE CPP                 #-}+{-# LANGUAGE DataKinds           #-}+{-# LANGUAGE FlexibleInstances   #-}+{-# LANGUAGE LambdaCase          #-}+{-# LANGUAGE NamedFieldPuns      #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE RankNTypes          #-}+{-# LANGUAGE RecordWildCards     #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeOperators       #-}+{-# LANGUAGE ViewPatterns        #-}+ {-# OPTIONS_GHC -fno-warn-orphans #-} +-- Build without optimizations to prevent out-of-memory situations in Hydra CI+{-# OPTIONS_GHC -O0 #-}+ module Dhall.Test.QuickCheck where -import Codec.Serialise (DeserialiseFailure(..))-import Data.Either (isRight)-import Data.List.NonEmpty (NonEmpty(..))-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(..)-    , Expr(..)-    , File(..)-    , FilePrefix(..)-    , Import(..)-    , ImportHashed(..)-    , ImportMode(..)-    , ImportType(..)-    , 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 Dhall.Set (Set)-import Dhall.Src (Src(..))-import Numeric.Natural (Natural)+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, genericShrink, (===), (==>))+    ( Arbitrary (..)+    , Gen+    , NonNegative (..)+    , Positive (..)+    , Property+    , genericShrink+    , suchThat+    , (===)+    , (==>)+    ) import Test.QuickCheck.Instances ()-import Test.Tasty (TestTree)-import Text.Megaparsec (SourcePos(..), Pos)+import Test.Tasty                (TestTree)+import Test.Tasty.QuickCheck     (QuickCheckTests (..))+import Text.Megaparsec           (Pos, SourcePos (..)) -import qualified Codec.Serialise-import qualified Data.Coerce+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 Dhall.Map+import qualified Data.Map import qualified Data.Sequence+import qualified Data.Set+import qualified Data.SpecialValues+import qualified Data.Text             as Text+import qualified Data.Time             as Time import qualified Dhall.Binary+import qualified Dhall.Context+import qualified Dhall.Core import qualified Dhall.Diff+import qualified Dhall.Map+import qualified Dhall.Parser          as Parser import qualified Dhall.Set import qualified Dhall.TypeCheck+import qualified Generic.Random+import qualified Lens.Micro            as Lens+import qualified Numeric.Natural       as Nat import qualified Test.QuickCheck+import qualified Test.Tasty import qualified Test.Tasty.QuickCheck import qualified Text.Megaparsec       as Megaparsec -newtype DeserialiseFailureWithEq = D DeserialiseFailure-    deriving (Show)--instance Eq DeserialiseFailureWithEq where-    D (DeserialiseFailure aL bL) == D (DeserialiseFailure aR bR) =-        aL == aR && bL == bR- instance (Arbitrary a, Ord a) => Arbitrary (Set a) where   arbitrary = Dhall.Set.fromList <$> arbitrary+  shrink = map Dhall.Set.fromList . shrink . Dhall.Set.toList  lift0 :: a -> Gen a lift0 = pure@@ -108,13 +163,6 @@         <*> arbitrary         <*> arbitrary -natural :: (Arbitrary a, Num a) => Gen a-natural =-    Test.QuickCheck.frequency-        [ (7, arbitrary)-        , (1, fmap (\x -> x + (2 ^ (64 :: Int))) arbitrary)-        ]- integer :: (Arbitrary a, Num a) => Gen a integer =     Test.QuickCheck.frequency@@ -123,10 +171,59 @@         , (1, fmap (\x -> x - (2 ^ (64 :: Int))) arbitrary)         ] -instance (Ord k, Arbitrary k, Arbitrary v) => Arbitrary (Map k v) where+whitespace :: Gen Text+whitespace = do+      let commentChar =+              Test.QuickCheck.frequency+                  [ (20, Test.QuickCheck.elements [' ' .. '\DEL'])+                  , ( 1, arbitrary)+                  ]++          noInteriorBlockComments text =+              not (Text.isInfixOf "{-" text || Text.isInfixOf "-}" text)++          commentText =+              suchThat+                  (Text.pack <$> Test.QuickCheck.listOf commentChar)+                  noInteriorBlockComments++          multiline = do+              txt <- commentText+              pure $ "{-" <> txt <> "-}"++          singleline = do+              txt <- commentText `suchThat` (not . Text.isInfixOf "\n")+              endOfLine <- Test.QuickCheck.elements ["\n", "\r\n"]+              pure $ "--" <> txt <> endOfLine++          newlines = Text.concat <$> Test.QuickCheck.listOf (pure "\n")++      comments <- do+          n <- Test.QuickCheck.choose (0, 2)+          Test.QuickCheck.vectorOf n $ Test.QuickCheck.oneof+              [ multiline+              , singleline+              , newlines+              ]++      pure $ Text.unlines comments++shrinkWhitespace :: Text -> [Text]+shrinkWhitespace "" = []+shrinkWhitespace _  = [""]++instance Arbitrary CharacterSet where+    arbitrary = Test.QuickCheck.elements [ ASCII, Unicode ]++instance Arbitrary Header where+    arbitrary = createHeader <$> whitespace++    shrink (Header text) = Header <$> shrinkWhitespace text++instance (Arbitrary v) => Arbitrary (Map Text v) where     arbitrary = do         n   <- Test.QuickCheck.choose (0, 2)-        kvs <- Test.QuickCheck.vectorOf n ((,) <$> 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)) @@ -136,8 +233,21 @@         .   Dhall.Map.toList  instance (Arbitrary s, Arbitrary a) => Arbitrary (Binding s a) where-    arbitrary = lift3 Binding+    arbitrary = do+        bindingSrc0 <- arbitrary +        variable <- Test.QuickCheck.oneof [ pure "_", label ]++        bindingSrc1 <- arbitrary++        annotation <- arbitrary++        bindingSrc2 <- arbitrary++        value <- arbitrary++        return Binding{..}+     shrink = genericShrink  instance (Arbitrary s, Arbitrary a) => Arbitrary (Chunks s a) where@@ -152,110 +262,210 @@      shrink = genericShrink +instance Arbitrary DhallDouble where+    arbitrary = fmap DhallDouble (Test.QuickCheck.oneof [ arbitrary, special ])+      where+        special = Test.QuickCheck.elements Data.SpecialValues.specialValues++    shrink = genericShrink+ instance Arbitrary Directory where     arbitrary = lift1 Directory      shrink = genericShrink -averageDepth :: Natural-averageDepth = 3+instance Arbitrary PreferAnnotation where+    arbitrary = Test.QuickCheck.oneof+        [ pure PreferFromSource+        , pure PreferFromCompletion+        ] -averageNumberOfSubExpressions :: Double-averageNumberOfSubExpressions = 1 - 1 / fromIntegral averageDepth+    shrink = genericShrink -probabilityOfNullaryConstructor :: Double-probabilityOfNullaryConstructor = 1 / fromIntegral averageDepth+instance (Arbitrary s, Arbitrary a) => Arbitrary (RecordField s a) where+    arbitrary = lift4 RecordField -numberOfConstructors :: Natural-numberOfConstructors = 50+    shrink = genericShrink +instance (Arbitrary s, Arbitrary a) => Arbitrary (FunctionBinding s a) where+    arbitrary = do+        l <- label+        type_ <- arbitrary+        return $ FunctionBinding Nothing l Nothing Nothing type_++    shrink = genericShrink++instance Arbitrary s => Arbitrary (FieldSelection s) where+    arbitrary = FieldSelection <$> pure Nothing <*> label <*> pure Nothing+    shrink = genericShrink++instance Arbitrary WithComponent where+    arbitrary =+        Test.QuickCheck.oneof [ pure WithQuestion, WithLabel <$> arbitrary ]+ instance (Arbitrary s, Arbitrary a) => Arbitrary (Expr s a) where     arbitrary =         Test.QuickCheck.suchThat-            (Test.QuickCheck.frequency-                [ ( 7, lift1 Const)-                , ( 7, lift1 Var)-                , ( 1, Test.QuickCheck.oneof [ lift2 (Lam "_"), lift3 Lam ])-                , ( 1, Test.QuickCheck.oneof [ lift2 (Pi "_"), lift3 Pi ])-                , ( 1, lift2 App)-                , let letExpression = do-                          n        <- Test.QuickCheck.choose (0, 2)-                          binding  <- arbitrary-                          bindings <- Test.QuickCheck.vectorOf n arbitrary-                          body     <- arbitrary-                          return (Let (binding :| bindings) body)-                  in  ( 1, Test.QuickCheck.oneof [ letExpression ])-                , ( 1, lift2 Annot)-                , ( 7, lift0 Bool)-                , ( 7, lift1 BoolLit)-                , ( 1, lift2 BoolAnd)-                , ( 1, lift2 BoolOr)-                , ( 1, lift2 BoolEQ)-                , ( 1, lift2 BoolNE)-                , ( 1, lift3 BoolIf)-                , ( 7, lift0 Natural)-                , ( 7, fmap NaturalLit natural)-                , ( 7, lift0 NaturalFold)-                , ( 7, lift0 NaturalBuild)-                , ( 7, lift0 NaturalIsZero)-                , ( 7, lift0 NaturalEven)-                , ( 7, lift0 NaturalOdd)-                , ( 7, lift0 NaturalToInteger)-                , ( 7, lift0 NaturalShow)-                , ( 1, lift2 NaturalPlus)-                , ( 1, lift2 NaturalTimes)-                , ( 7, lift0 Integer)-                , ( 7, fmap IntegerLit integer)-                , ( 7, lift0 IntegerShow)-                , ( 7, lift0 Double)-                , ( 7, lift1 DoubleLit)-                , ( 7, lift0 DoubleShow)-                , ( 7, lift0 Text)-                , ( 1, lift1 TextLit)-                , ( 1, lift2 TextAppend)-                , ( 7, lift0 List)-                , let listLit = do-                          n  <- Test.QuickCheck.choose (0, 3)-                          xs <- Test.QuickCheck.vectorOf n arbitrary-                          let ys = Data.Sequence.fromList xs-                          ListLit <$> arbitrary <*> pure ys+            (Generic.Random.withBaseCase+                (Generic.Random.genericArbitraryRecG customGens weights)+                (Var <$> arbitrary)+                )+            standardizedExpression+      where+        customGens+            :: ConstrGen "Lam" 1 (FunctionBinding s a)+            :+ ConstrGen "Pi" 1 Text+            :+ ConstrGen "Field" 1 (FieldSelection s)+            :+ ConstrGen "Project" 1 (Either [Text] (Expr s a))+            :+ Gen Integer  -- Generates all Integer fields in Expr+            :+ Gen Text     -- Generates all Text fields in Expr+            :+ ()+        customGens =+               ConstrGen arbitrary+            :+ ConstrGen label+            :+ ConstrGen arbitrary+            :+ ConstrGen projection+            :+ integer+               -- 'Lam's and 'Pi's are encoded differently when the binding is+               -- the special string "_", so we generate some of these strings+               -- to improve test coverage for these code paths.+            :+ Test.QuickCheck.oneof [pure "_", arbitrary]+            :+ () -                  in  ( 1, listLit)-                , ( 1, lift2 ListAppend)-                , ( 7, lift0 ListBuild)-                , ( 7, lift0 ListFold)-                , ( 7, lift0 ListLength)-                , ( 7, lift0 ListHead)-                , ( 7, lift0 ListLast)-                , ( 7, lift0 ListIndexed)-                , ( 7, lift0 ListReverse)-                , ( 7, lift0 Optional)-                , ( 1, lift2 OptionalLit)-                , ( 7, lift0 OptionalFold)-                , ( 7, lift0 OptionalBuild)-                , ( 1, lift1 Record)-                , ( 1, lift1 RecordLit)-                , ( 1, lift1 Union)-                , ( 1, lift3 UnionLit)-                , ( 1, lift2 Combine)-                , ( 1, lift2 CombineTypes)-                , ( 1, lift2 Prefer)-                , ( 1, lift3 Merge)-                , ( 1, lift2 Field)-                , ( 1, lift2 Project)-                , ( 7, lift1 Embed)+        projection =+            Test.QuickCheck.oneof+                [ fmap Left (Test.QuickCheck.listOf label)+                , arbitrary                 ]-            )-            standardizedExpression +        -- These weights determine the frequency of constructors in the generated+        -- Expr.+        -- They will fail to compile if the constructors don't appear in the order+        -- in which they are defined in 'Expr'!+        weights :: Weights (Expr s a)+        weights =+              (7 :: W "Const")+            % (7 :: W "Var")+            % (7 :: W "Lam")+            % (7 :: W "Pi")+            % (7 :: W "App")+            % (7 :: W "Let")+            % (1 :: W "Annot")+            % (1 :: W "Bool")+            % (7 :: W "BoolLit")+            % (1 :: W "BoolAnd")+            % (1 :: W "BoolOr")+            % (1 :: W "BoolEQ")+            % (1 :: W "BoolNE")+            % (1 :: W "BoolIf")+            % (1 :: W "Bytes")+            % (1 :: W "BytesLit")+            % (1 :: W "Natural")+            % (7 :: W "NaturalLit")+            % (1 :: W "NaturalFold")+            % (1 :: W "NaturalBuild")+            % (1 :: W "NaturalIsZero")+            % (1 :: W "NaturalEven")+            % (1 :: W "NaturalOdd")+            % (1 :: W "NaturalToInteger")+            % (1 :: W "NaturalShow")+            % (1 :: W "NaturalSubtract")+            % (1 :: W "NaturalPlus")+            % (1 :: W "NaturalTimes")+            % (1 :: W "Integer")+            % (7 :: W "IntegerLit")+            % (1 :: W "IntegerClamp")+            % (1 :: W "IntegerNegate")+            % (1 :: W "IntegerShow")+            % (1 :: W "IntegerToDouble")+            % (1 :: W "Double")+            % (7 :: W "DoubleLit")+            % (1 :: W "DoubleShow")+            % (1 :: W "Text")+            % (1 :: W "TextLit")+            % (1 :: W "TextAppend")+            % (1 :: W "TextReplace")+            % (1 :: W "TextShow")+            % (1 :: W "Date")+            % (1 :: W "DateLiteral")+            % (1 :: W "DateShow")+            % (1 :: W "Time")+            % (1 :: W "TimeLiteral")+            % (1 :: W "TimeShow")+            % (1 :: W "TimeZone")+            % (1 :: W "TimeZoneLiteral")+            % (1 :: W "TimeZoneShow")+            % (1 :: W "List")+            % (1 :: W "ListLit")+            % (1 :: W "ListAppend")+            % (1 :: W "ListBuild")+            % (1 :: W "ListFold")+            % (1 :: W "ListLength")+            % (1 :: W "ListHead")+            % (1 :: W "ListLast")+            % (1 :: W "ListIndexed")+            % (1 :: W "ListReverse")+            % (1 :: W "Optional")+            % (7 :: W "Some")+            % (1 :: W "None")+            % (1 :: W "Record")+            % (7 :: W "RecordLit")+            % (1 :: W "Union")+            % (7 :: W "Combine")+            % (1 :: W "CombineTypes")+            % (7 :: W "Prefer")+            % (7 :: W "RecordCompletion")+            % (1 :: W "Merge")+            % (1 :: W "ToMap")+            % (1 :: W "ShowConstructor")+            % (7 :: W "Field")+            % (7 :: W "Project")+            % (1 :: W "Assert")+            % (1 :: W "Equivalent")+            % (1 :: W "With")+            % (0 :: W "Note")+            % (7 :: W "ImportAlt")+            % (7 :: W "Embed")+            % ()+     shrink expression = filter standardizedExpression (genericShrink expression)  standardizedExpression :: Expr s a -> Bool-standardizedExpression (ListLit  Nothing  xs) = not (Data.Sequence.null xs)-standardizedExpression (ListLit (Just _ ) xs) = Data.Sequence.null xs-standardizedExpression (Note _ _            ) = False-standardizedExpression  _                     = True+standardizedExpression (ListLit  Nothing  xs) =+    not (Data.Sequence.null xs)+standardizedExpression (ListLit (Just _ ) xs) =+    Data.Sequence.null xs+standardizedExpression (Note _ _) =+    False+standardizedExpression (Combine _ (Just _) _ _) =+    False+standardizedExpression With{} =+    False+standardizedExpression (Prefer _ PreferFromCompletion _ _) =+    False+-- The following three expressions are valid ASTs, but they can never be parsed,+-- because the annotation will associate with `Merge`/`ListLit`/`ToMap` with+-- higher precedence+standardizedExpression (Annot (Merge _ _ Nothing) _) =+    False+standardizedExpression (Annot (ListLit Nothing _) _) =+    False+standardizedExpression (Annot (ToMap _ Nothing) _) =+    False+standardizedExpression (TimeZoneLiteral (Time.TimeZone _ b t)) =+    not b && null t+standardizedExpression (TimeLiteral (Time.TimeOfDay _ _ ss) precision) =+    isInteger (ss * magnitude)+  where+    magnitude = 10 ^ precision +    isInteger x = x == fromInteger (round x)+standardizedExpression _ =+    True++chooseCharacter :: (Char, Char) -> Gen Char+chooseCharacter = Test.QuickCheck.chooseEnum+ instance Arbitrary File where     arbitrary = lift2 File @@ -267,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@@ -282,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             ]@@ -302,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 = lift0 Code+    arbitrary = Test.QuickCheck.elements [ Code, RawText, Location, RawBytes ]      shrink = genericShrink @@ -317,64 +544,259 @@     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 "_") (fromIntegral <$> (natural :: Gen Int))-            , lift1 (\t -> V t 0)-            , lift1 V <*> (fromIntegral <$> (natural :: Gen Int))+            [ fmap (V "_") (getNonNegative <$> arbitrary)+            , fmap (\t -> V t 0) label+            , V <$> label <*> (getNonNegative <$> arbitrary)             ]-     shrink = genericShrink +label :: Gen Text+label = fmap Text.pack (Test.QuickCheck.listOf labelCharacter)+  where+    labelCharacter =+        Test.QuickCheck.frequency+            [ (64, chooseCharacter ('\x20', '\x5F'))+            , (30, chooseCharacter ('\x61', '\x7e'))+            ]+ binaryRoundtrip :: Expr () Import -> Property binaryRoundtrip expression =-        wrap-            (fmap-                Dhall.Binary.decodeExpression-                (Codec.Serialise.deserialiseOrFail-                  (Codec.Serialise.serialise-                    (Dhall.Binary.encodeExpression expression)-                  )-                )-            )-    === wrap (Right (Right expression))+        Dhall.Binary.decodeExpression (Dhall.Binary.encodeExpression denotedExpression)+    === Right denotedExpression   where-    wrap-        :: Either DeserialiseFailure       a-        -> Either DeserialiseFailureWithEq a-    wrap = Data.Coerce.coerce+    denotedExpression :: Expr Void Import+    denotedExpression = denote' expression --- isNormalizedIsConsistentWithNormalize :: Expr () Import -> Property--- isNormalizedIsConsistentWithNormalize expression =---         Dhall.Core.isNormalized expression---     === (Dhall.Core.normalize expression == expression)+    denote' :: Expr a Import -> Expr b Import+    denote' = Dhall.Core.denote . fmap denoteHttpHeaders +    denoteHttpHeaders import_@(Import importHashed _)+        | Remote url <- importType importHashed+        = let headers' = denote' <$> headers url+              importType' = Remote url { headers = headers' }+              importHashed' = importHashed { importType = importType' }+          in  import_ {importHashed = importHashed'}+        | otherwise = import_++everythingWellTypedNormalizes :: Expr () () -> Property+everythingWellTypedNormalizes expression =+        isRight (Dhall.TypeCheck.typeWithA filterOutEmbeds Dhall.Context.empty expression)+    ==> Test.QuickCheck.total (Dhall.Core.normalize expression :: Expr () ())+  where+    filterOutEmbeds :: Typer a+    filterOutEmbeds _ = Const Sort -- This could be any ill-typed expression.++isNormalizedIsConsistentWithNormalize :: Expr () Import -> Property+isNormalizedIsConsistentWithNormalize expression =+    case maybeProp of+        Nothing -> Test.QuickCheck.discard+        Just v -> v+  where+      denotedExpression :: Expr Void Import+      denotedExpression = Dhall.Core.denote expression++      maybeProp = do+          nf <- Control.Spoon.spoon (Dhall.Core.normalize expression)+          isNormalized <- Control.Spoon.spoon (Dhall.Core.isNormalized expression)+          -- Dhall.Core.isNormalized ignores 'Note's and other annotations.+          -- So we do the same when checking the result of 'normalize'.+          return $ isNormalized === (nf == denotedExpression)++normalizeWithMIsConsistentWithNormalize :: Expr () Import -> Property+normalizeWithMIsConsistentWithNormalize expression =+    case Control.Spoon.spoon (nfM, nf) of+        Just (a, b) -> a === b+        Nothing -> Test.QuickCheck.discard+  where nfM = runIdentity (Dhall.Core.normalizeWithM (\_ -> Identity Nothing) expression)+        nf = Dhall.Core.normalize expression :: Expr () Import+ isSameAsSelf :: Expr () Import -> Property isSameAsSelf expression =-  hasNoImportAndTypechecks ==> Dhall.Diff.same (Dhall.Diff.diffExpression expression expression)-  where hasNoImportAndTypechecks =+  hasNoImportAndTypechecks ==> Dhall.Diff.same (Dhall.Diff.diff denoted denoted)+  where denoted = Dhall.Core.denote expression+        hasNoImportAndTypechecks =           case traverse (\_ -> Left ()) expression of             Right importlessExpression -> isRight (Dhall.TypeCheck.typeOf importlessExpression)             Left _ -> False +inferredTypesAreNormalized :: Expr () Import -> Property+inferredTypesAreNormalized expression =+    Test.Tasty.QuickCheck.counterexample report (all Dhall.Core.isNormalized result)+  where+    report =  "Got: " ++ show result+           ++ "\nExpected: " ++ show (fmap Dhall.Core.normalize result+                                      :: Either (TypeError () Import) (Expr () Import))++    result = Dhall.TypeCheck.typeWithA filterOutEmbeds Dhall.Context.empty expression++    filterOutEmbeds :: Typer a+    filterOutEmbeds _ = Const Sort -- This could be any ill-typed expression.++normalizingAnExpressionDoesntChangeItsInferredType :: Expr () Import -> Property+normalizingAnExpressionDoesntChangeItsInferredType expression =+    case (eT0, eT1) of+        (Right t0, Right t1) -> t0 === t1+        _ -> Test.QuickCheck.discard+  where+    eT0 = typeCheck expression+    eT1 = typeCheck (Dhall.Core.normalize expression)++    typeCheck = Dhall.TypeCheck.typeWithA filterOutEmbeds Dhall.Context.empty++    filterOutEmbeds :: Typer a+    filterOutEmbeds _ = Const Sort -- This could be any ill-typed expression.++noDoubleNotes :: Expr () Import -> Property+noDoubleNotes expression =+    length+        [ ()+        | e <- Foldable.toList parsedExpression+        , Note _ (Note _ _) <- Lens.toListOf Dhall.Core.subExpressions e+        ] === 0+  where+    text = Dhall.Core.pretty expression++    parsedExpression = Parser.exprFromText "" text++embedThenExtractIsIdentity+    :: forall a. (ToDhall a, FromDhall a, Eq a, Typeable a, Arbitrary a, Show a)+    => Proxy a+    -> (String, Property, TestTree -> TestTree)+embedThenExtractIsIdentity p =+    ( "Embedding then extracting is identity for " ++ show (typeRep p)+    , Test.QuickCheck.property (prop :: a -> Bool)+    , adjustQuickCheckTests 1000+    )+  where+    prop a = case extract auto (embed inject a) of+        Success a' -> a == a'+        Failure _  -> False++idempotenceTest :: CharacterSet -> Header -> Expr Src Import -> Property+idempotenceTest characterSet header expr =+        not (any hasHttpHeaders expr)+    ==> let once = format characterSet (header, expr)+        in case Parser.exprAndHeaderFromText mempty once of+            Right (format characterSet -> twice) -> once === twice+            Left _ -> Test.QuickCheck.discard+  where+    -- Workaround for https://github.com/dhall-lang/dhall-haskell/issues/1925.+    hasHttpHeaders = \case+        Import (ImportHashed _ (Remote (URL { headers = Just _ }))) _ -> True+        _                                                             -> False+ tests :: TestTree tests =-    Test.Tasty.QuickCheck.testProperties+    testProperties'         "QuickCheck"         [ ( "Binary serialization should round-trip"           , Test.QuickCheck.property binaryRoundtrip+          , adjustQuickCheckTests 100           )-        -- , ( "isNormalized should be consistent with normalize"-        --   , Test.QuickCheck.property-        --       (Test.QuickCheck.withMaxSuccess 10000 isNormalizedIsConsistentWithNormalize)-        --   )+        , ( "everything well-typed should normalize"+          , Test.QuickCheck.property everythingWellTypedNormalizes+          , adjustQuickCheckTests 100000+          )+        , ( "isNormalized should be consistent with normalize"+          , Test.QuickCheck.property isNormalizedIsConsistentWithNormalize+          , adjustQuickCheckTests 10000+          )+        , ( "normalizeWithM should be consistent with normalize"+          , Test.QuickCheck.property normalizeWithMIsConsistentWithNormalize+          , adjustQuickCheckTests 10000+          )         , ( "An expression should have no difference with itself"-          , Test.QuickCheck.property-              (Test.QuickCheck.withMaxSuccess 10000 isSameAsSelf)+          , Test.QuickCheck.property isSameAsSelf+          , adjustQuickCheckTests 10000           )+        , ( "Inferred types should be normalized"+          , Test.QuickCheck.property inferredTypesAreNormalized+          , adjustQuickCheckTests 10000+          )+        , ( "Normalizing an expression doesn't change its inferred type"+          , Test.QuickCheck.property normalizingAnExpressionDoesntChangeItsInferredType+          , adjustQuickCheckTests 10000+          )+        , ( "Parsing an expression doesn't generated doubly-nested Note constructors"+          , Test.QuickCheck.property noDoubleNotes+          , adjustQuickCheckTests 100+          )+        , embedThenExtractIsIdentity (Proxy :: Proxy (Text))+        , embedThenExtractIsIdentity (Proxy :: Proxy [Nat.Natural])+        , embedThenExtractIsIdentity (Proxy :: Proxy (Bool, Double))+        , embedThenExtractIsIdentity (Proxy :: Proxy (Data.Sequence.Seq ()))+        , embedThenExtractIsIdentity (Proxy :: Proxy (Maybe Integer))+        , embedThenExtractIsIdentity (Proxy :: Proxy (Data.Set.Set Nat.Natural))+        , embedThenExtractIsIdentity (Proxy :: Proxy (Data.HashSet.HashSet Text))+        , embedThenExtractIsIdentity (Proxy :: Proxy (Vector Double))+        , embedThenExtractIsIdentity (Proxy :: Proxy (Data.Map.Map Double Bool))+        , embedThenExtractIsIdentity (Proxy :: Proxy (HashMap.HashMap Double Bool))+        , ( "Formatting should be idempotent"+          , Test.QuickCheck.property idempotenceTest+          , adjustQuickCheckTests 10000+          )         ]++adjustQuickCheckMaxRatio :: Int -> TestTree -> TestTree+adjustQuickCheckMaxRatio maxSize =+    Test.Tasty.adjustOption (max $ Test.Tasty.QuickCheck.QuickCheckMaxRatio maxSize)++adjustQuickCheckTests :: Int -> TestTree -> TestTree+adjustQuickCheckTests nTests =+    -- Using adjustOption instead of withMaxSuccess allows us to override the number of tests+    -- with the --quickcheck-tests CLI option.+    Test.Tasty.adjustOption (max $ QuickCheckTests nTests)++testProperties' :: String -> [(String, Property, TestTree -> TestTree)] -> TestTree+testProperties' name = Test.Tasty.testGroup name . map f+  where+    f (n, p, adjust) = adjust (Test.Tasty.QuickCheck.testProperty n p)
tests/Dhall/Test/Regression.hs view
@@ -1,31 +1,37 @@ {-# LANGUAGE DeriveAnyClass    #-} {-# LANGUAGE DeriveGeneric     #-}+{-# LANGUAGE FlexibleContexts  #-} {-# LANGUAGE OverloadedStrings #-}  module Dhall.Test.Regression where +import Data.Either.Validation (Validation (..))+import Data.Void              (Void)+import Dhall.Core             (Expr (..), ReifiedNormalizer (..))+import Dhall.Import           (Imported, MissingImports (..))+import Dhall.Parser           (SourcedException (..), Src)+import Dhall.TypeCheck        (TypeError)+import Test.Tasty             (TestTree)+import Test.Tasty.HUnit       ((@?=))+ import qualified Control.Exception+import qualified Data.Text.IO import qualified Data.Text.Lazy.IO-import qualified 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 Dhall.Import (Imported)-import Dhall.Parser (Src)-import Dhall.TypeCheck (TypeError, X)-import Test.Tasty (TestTree)-import Test.Tasty.HUnit ((@?=))- tests :: TestTree tests =     Test.Tasty.testGroup "regression tests"@@ -36,6 +42,15 @@         , issue201         , issue216         , issue253+        , issue1131a+        , issue1131b+        , issue1341+        , issue1584+        , issue1646+        , issue1732+        , issue1884+        , issue2088+        , issue2463         , parsing0         , typeChecking0         , typeChecking1@@ -45,33 +60,43 @@         ]  data Foo = Foo Integer Bool | Bar Bool Bool Bool | Baz Integer Integer-    deriving (Show, Dhall.Generic, Dhall.Interpret, Dhall.Inject)+    deriving (Show, Dhall.Generic, Dhall.FromDhall, Dhall.ToDhall)  unnamedFields :: TestTree unnamedFields = Test.Tasty.HUnit.testCase "Unnamed Fields" (do-    let ty = Dhall.auto :: Dhall.Type Foo+    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.InputType Foo-    Test.Tasty.HUnit.assertEqual "Good Inject" (Dhall.declared inj) (Dhall.expected ty)+    let inj = Dhall.inject :: Dhall.Encoder Foo+    Test.Tasty.HUnit.assertEqual "Good ToDhall" (Success $ Dhall.declared inj) (Dhall.expected ty) -    let tu_ty = Dhall.auto :: Dhall.Type (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) ]))+    let tu_ty = Dhall.auto :: Dhall.Decoder (Integer, Bool)+    Test.Tasty.HUnit.assertEqual "Auto Tuple" (Dhall.expected tu_ty) (Success $ Dhall.Core.Record (+            Dhall.Map.fromList+                [ ("_1", Dhall.Core.makeRecordField Dhall.Core.Integer)+                , ("_2", Dhall.Core.makeRecordField Dhall.Core.Bool)+                ])) -    let tu_in = Dhall.inject :: Dhall.InputType (Integer, Bool)-    Test.Tasty.HUnit.assertEqual "Inj. Tuple" (Dhall.declared tu_in) (Dhall.expected tu_ty)+    let tu_in = Dhall.inject :: Dhall.Encoder (Integer, Bool)+    Test.Tasty.HUnit.assertEqual "Inj. Tuple" (Success $ Dhall.declared tu_in) (Dhall.expected tu_ty)      return () ) @@ -89,8 +114,13 @@ issue151 :: TestTree issue151 = Test.Tasty.HUnit.testCase "Issue #151" (do     let shouldNotTypeCheck text = do-            let handler :: Imported (TypeError Src X) -> IO Bool-                handler _ = return True+            let handler :: SourcedException MissingImports -> IO Bool+                handler (SourcedException _ (MissingImports [e])) =+                    case Control.Exception.fromException e :: Maybe (Imported (TypeError Src Void)) of+                        Just _ -> return True+                        Nothing -> return False+                handler _ =+                    return True              let typeCheck = do                     _ <- Util.code text@@ -133,10 +163,11 @@ issue216 :: TestTree issue216 = Test.Tasty.HUnit.testCase "Issue #216" (do     -- Verify that pretty-printing preserves string interpolation-    e <- Util.code "./tests/regression/issue216a.dhall"-    let doc       = Data.Text.Prettyprint.Doc.pretty e-    let docStream = Data.Text.Prettyprint.Doc.layoutSmart Dhall.Pretty.layoutOpts doc-    let text0 = Data.Text.Prettyprint.Doc.Render.Text.renderLazy docStream+    source <- Data.Text.IO.readFile "./tests/regression/issue216b.dhall"+    e <- Util.code source+    let doc       = Prettyprinter.pretty e+    let docStream = Dhall.Pretty.layout doc+    let text0 = Prettyprinter.Render.Text.renderLazy docStream      text1 <- Data.Text.Lazy.IO.readFile "./tests/regression/issue216b.dhall" @@ -145,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@@ -153,12 +184,80 @@     Just _ <- System.Timeout.timeout 1000000 (Control.Exception.evaluate $! result)     return () ) +issue1131a :: TestTree+issue1131a = Test.Tasty.HUnit.testCase "Issue #1131 a"+    (Util.assertDoesntTypeCheck "toMap {=} : <>.x")++issue1131b :: TestTree+issue1131b = Test.Tasty.HUnit.testCase "Issue #1131 b"+    (Util.assertDoesntTypeCheck "toMap {=} : List {mapKey : Text, mapValue : 0}")++issue1341 :: TestTree+issue1341 = Test.Tasty.HUnit.testCase "Issue #1341" (do+    let nan    = Dhall.Core.DoubleLit (Dhall.Core.DhallDouble (0/0)) :: Dhall.Core.Expr () ()+    let actual = Dhall.Core.V "x" 0 `Dhall.Core.freeIn` nan+    let msg    = "NaN shouldn't contain any free variables"+    Test.Tasty.HUnit.assertEqual msg False actual)++issue1584 :: TestTree+issue1584 = Test.Tasty.HUnit.testCase "Issue #1584" (do+    -- This test ensures that we can parse variables with keyword prefixes+    -- (e.g. `ifX`)+    _ <- Util.code "./tests/regression/issue1584.dhall"+    return () )++issue1646 :: TestTree+issue1646 = Test.Tasty.HUnit.testCase "Issue #1646" (do+    -- This test ensures that the parser doesn't eagerly consume trailing+    -- whitespace after a `Double`+    _ <- Util.code "./tests/regression/issue1646.dhall"+    return () )++issue1732 :: TestTree+issue1732 = Test.Tasty.HUnit.testCase "Issue #1732" (do+    -- This test ensures that the parser allows whitespace after a record pun+    -- entry+    _ <- Util.code "./tests/regression/issue1732.dhall"+    return () )++issue1884 :: TestTree+issue1884 = Test.Tasty.HUnit.testCase "Issue #1884" (do+    -- This test ensures that the parser allows a parenthesized application+    -- expression as the first argument to a with expression+    _ <- Util.code "./tests/regression/issue1884.dhall"+    return () )++issue2088 :: TestTree+issue2088 = Test.Tasty.HUnit.testCase "Issue #2088" (do+    -- This test ensures that the parser for projection by labels doesn't+    -- accidentally swallow trailing commas OUTSIDE of the projection+    _ <- Util.code "./tests/regression/issue2088.dhall"+    return () )++issue2463 :: TestTree+issue2463 = Test.Tasty.HUnit.testCase "Issue #2463" (do+    let startingContext = Context.insert "foo" Integer Context.empty++    let normalizer (Var "foo") = Just (IntegerLit 0)+        normalizer  _          = Nothing++    let inputSettings = transform Dhall.defaultInputSettings+          where+            transform =+                  Lens.set Dhall.normalizer+                      (Just (ReifiedNormalizer (pure . normalizer)))+                . Lens.set Dhall.startingContext startingContext++    x <- Dhall.inputWithSettings inputSettings Dhall.auto "foo"++    Test.Tasty.HUnit.assertEqual "" (0 :: Integer) x )+ parsing0 :: TestTree-parsing0 = Test.Tasty.HUnit.testCase "Parsing regression #0" (do+parsing0 = Test.Tasty.HUnit.testCase "Parsing regression #0" (     -- Verify that parsing should not fail     --     -- In 267093f8cddf1c2f909f2d997c31fd0a7cb2440a I broke the parser when left-    -- factoring the grammer by failing to handle the source tested by this+    -- factoring the grammar by failing to handle the source tested by this     -- regression test.  The root of the problem was that the parser was trying     -- to parse `List ./Node` as `Field List "/Node"` instead of     -- `App List (Embed (Path (File Homeless "./Node") Code))`.  The latter is
+ tests/Dhall/Test/Schemas.hs view
@@ -0,0 +1,61 @@+{-# LANGUAGE OverloadedStrings #-}++module Dhall.Test.Schemas where++import Data.Text    (Text)+import Dhall.Parser (Header (..))+import Test.Tasty   (TestTree)++import qualified Data.Text                 as Text+import qualified Data.Text.IO              as Text.IO+import qualified Dhall.Core                as Core+import qualified Dhall.Parser              as Parser+import qualified Dhall.Pretty              as Pretty+import qualified Dhall.Schemas             as Schemas+import qualified Dhall.Test.Util           as Test.Util+import qualified Prettyprinter             as Doc+import qualified Prettyprinter.Render.Text as Doc.Render.Text+import qualified Test.Tasty                as Tasty+import qualified Test.Tasty.HUnit          as Tasty.HUnit+import qualified Turtle++schemasDirectory :: FilePath+schemasDirectory = "./tests/schemas"++getTests :: IO TestTree+getTests = do+    schemasTests <- Test.Util.discover (Turtle.chars <* "A.dhall") schemaTest (Turtle.lstree schemasDirectory)++    return (Tasty.testGroup "schemas tests" [ schemasTests ])++format :: Header -> Core.Expr Parser.Src Core.Import -> Text+format (Header header) expr =+    let doc =  Doc.pretty header+            <> Pretty.prettyCharacterSet Pretty.Unicode expr+            <> "\n"++        docStream = Pretty.layout doc+    in+        Doc.Render.Text.renderStrict docStream++schemaTest :: Text -> TestTree+schemaTest prefix =+    Tasty.HUnit.testCase (Text.unpack prefix) $ do+        let inputFile  = Text.unpack (prefix <> "A.dhall")+        let outputFile = Text.unpack (prefix <> "B.dhall")++        inputText  <- Text.IO.readFile inputFile++        (header, parsedInput) <- Core.throws (Parser.exprAndHeaderFromText mempty inputText)++        parsedSchema <- Core.throws (Parser.exprFromText mempty (Test.Util.toDhallPath (prefix <> "Schema.dhall")))++        actualExpression <- Schemas.rewriteWithSchemas parsedSchema parsedInput++        let actualText = format header actualExpression++        expectedText <- Text.IO.readFile outputFile++        let message = "The rewritten expression did not match the expected output"++        Tasty.HUnit.assertEqual message expectedText actualText
+ tests/Dhall/Test/SemanticHash.hs view
@@ -0,0 +1,45 @@+{-# LANGUAGE OverloadedStrings #-}++module Dhall.Test.SemanticHash where++import Data.Text  (Text)+import Test.Tasty (TestTree)++import qualified Data.Text        as Text+import qualified Data.Text.IO     as Text.IO+import qualified Dhall.Core       as Core+import qualified Dhall.Import     as Import+import qualified Dhall.Parser     as Parser+import qualified Dhall.Test.Util  as Test.Util+import qualified Test.Tasty       as Tasty+import qualified Test.Tasty.HUnit as Tasty.HUnit+import qualified Turtle++hashDirectory :: FilePath+hashDirectory = "./dhall-lang/tests/semantic-hash"++getTests :: IO TestTree+getTests = do+    hashTests <- Test.Util.discover (Turtle.chars <* "A.dhall") hashTest (Turtle.lstree hashDirectory)++    return (Tasty.testGroup "semantic-hash tests" [ hashTests ])++hashTest :: Text -> TestTree+hashTest prefix =+    Tasty.HUnit.testCase (Text.unpack prefix) $ do+        let codeFile = Test.Util.toDhallPath (prefix <> "A.dhall")+        let hashFile = Test.Util.toDhallPath (prefix <> "B.hash")++        expr <- Core.throws (Parser.exprFromText mempty codeFile)++        resolved <- Import.load expr++        let normalized = Core.alphaNormalize (Core.normalize resolved)++        let actualHash = Import.hashExpressionToCode normalized++        expectedHash <- Text.stripEnd <$> Text.IO.readFile (Text.unpack hashFile)++        let message = "The hash did not match the expected hash."++        Tasty.HUnit.assertEqual message expectedHash actualHash
+ tests/Dhall/Test/Substitution.hs view
@@ -0,0 +1,38 @@+{-# LANGUAGE DeriveGeneric     #-}+{-# LANGUAGE OverloadedStrings #-}++module Dhall.Test.Substitution where++import Control.Exception (throwIO)+import Data.Void         (Void)+import Dhall.Core        (Expr (BoolLit, Var))+import Dhall.Src         (Src)++import qualified Data.Either.Validation+import qualified Dhall+import qualified Dhall.Map+import qualified Lens.Micro             as Lens++data Result = Failure Integer | Success String+    deriving (Eq, Dhall.Generic, Show)++instance Dhall.FromDhall Result++substituteResult :: FilePath -> IO Result+substituteResult fp = do+    rt <- resultType+    let evaluateSettings = Lens.over Dhall.substitutions (Dhall.Map.insert "Result" rt) Dhall.defaultEvaluateSettings+    Dhall.inputFileWithSettings evaluateSettings resultDecoder fp++resultDecoder :: Dhall.Decoder Result+resultDecoder = Dhall.auto++resultType :: IO (Expr Src Void)+resultType = case Dhall.expected resultDecoder of+    Data.Either.Validation.Failure e -> throwIO e+    Data.Either.Validation.Success x -> return x++substituteFoo :: FilePath -> IO Bool+substituteFoo fp = let+    evaluateSettings = Lens.set Dhall.substitutions (Dhall.Map.fromList [("Foo", Var "Bar"), ("Bar", BoolLit True)]) Dhall.defaultEvaluateSettings+    in Dhall.inputFileWithSettings evaluateSettings Dhall.auto fp
+ tests/Dhall/Test/TH.hs view
@@ -0,0 +1,219 @@+{-# LANGUAGE DeriveAnyClass     #-}+{-# LANGUAGE DeriveGeneric      #-}+{-# LANGUAGE DerivingStrategies #-}+{-# LANGUAGE FlexibleInstances  #-}+{-# LANGUAGE OverloadedStrings  #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TemplateHaskell    #-}++module Dhall.Test.TH where++import Control.Exception      (throwIO)+import Data.Either.Validation (Validation (..))+import Data.Time              (TimeOfDay (..), TimeZone (..), fromGregorian)+import Dhall.TH               (HaskellType (..))+import Test.Tasty             (TestTree)++import qualified Data.Text+import qualified Dhall+import qualified Dhall.TH+import qualified Test.Tasty       as Tasty+import qualified Test.Tasty.HUnit as Tasty.HUnit++Dhall.TH.makeHaskellTypeFromUnion "T" "./tests/th/example.dhall"++deriving instance Eq   T+deriving instance Show T++Dhall.TH.makeHaskellTypes+    [ MultipleConstructors "Department" "./tests/th/Department.dhall"+    , SingleConstructor "Employee" "MakeEmployee" "./tests/th/Employee.dhall"+    , SingleConstructor "TimeExample" "TimeExample" "./tests/th/Time.dhall"+    ]++deriving instance Eq   Department+deriving instance Show Department++deriving instance Eq   Employee+deriving instance Show Employee++deriving instance Eq   TimeExample+deriving instance Show TimeExample++Dhall.TH.makeHaskellTypes+  [ SingleConstructor "Bar" "MakeBar" "(./tests/th/issue2066.dhall).Bar"+  , SingleConstructor "Foo" "MakeFoo" "(./tests/th/issue2066.dhall).Foo"+  , MultipleConstructors "Qux" "(./tests/th/issue2066.dhall).Qux"+  ]++deriving instance Eq   Bar+deriving instance Show Bar++deriving instance Eq   Foo+deriving instance Show Foo++deriving instance Eq   Qux+deriving instance Show Qux++tests :: TestTree+tests = Tasty.testGroup "Template Haskell" [ makeHaskellTypeFromUnion ]++makeHaskellTypeFromUnion :: TestTree+makeHaskellTypeFromUnion = Tasty.HUnit.testCase "makeHaskellTypeFromUnion" $ do+    t0 <- Dhall.input Dhall.auto "let T = ./tests/th/example.dhall in T.A { x = True, y = [ \"ABC\" ] }"++    Tasty.HUnit.assertEqual "" t0 A{ x = True, y = [ "ABC" ] }++    t1 <- Dhall.input Dhall.auto "let T = ./tests/th/example.dhall in T.B (Some [ 1 ])"++    Tasty.HUnit.assertEqual "" t1 (B (Just [ 1 ]))++    t2 <- Dhall.input Dhall.auto "let T = ./tests/th/example.dhall in T.C"++    Tasty.HUnit.assertEqual "" t2 C++    employee <- Dhall.input Dhall.auto "let Department = ./tests/th/Department.dhall in { name = \"John\", department = Department.Marketing }"++    Tasty.HUnit.assertEqual "" employee MakeEmployee{ name = "John", department = Marketing }++    qux <- Dhall.input Dhall.auto "let T = ./tests/th/issue2066.dhall in T.Qux.Foo { foo = +2, bar = { baz = +3 } }"++    Tasty.HUnit.assertEqual "" qux (Foo MakeFoo{ foo = 2, bar = MakeBar{ baz = 3 } })++    timex <- Dhall.input Dhall.auto "let T = ./tests/th/Time.dhall in { txTime = 21:12:00, txDate = 1976-04-01, txTimeZone = +05:00 } : T"++    Tasty.HUnit.assertEqual "" timex TimeExample { txTime = tod, txDate = day, txTimeZone = tz}++    where+      tod = TimeOfDay { todHour = 21, todMin = 12, todSec = 0 }+      day = fromGregorian 1976 4 1+      tz = TimeZone { timeZoneMinutes = 300, timeZoneSummerOnly = False, timeZoneName = "" }+  ++Dhall.TH.makeHaskellTypesWith (Dhall.TH.defaultGenerateOptions+    { Dhall.TH.constructorModifier = ("My" <>)+    , Dhall.TH.fieldModifier = ("my" <>) . Data.Text.toTitle+    })+    [ MultipleConstructors "MyT" "./tests/th/example.dhall"+    , MultipleConstructors "MyDepartment" "./tests/th/Department.dhall"+    , SingleConstructor "MyEmployee" "Employee" "./tests/th/Employee.dhall"+    ]++  +deriving instance Eq   MyT+deriving instance Eq   MyDepartment+deriving instance Eq   MyEmployee+deriving instance Show MyT+deriving instance Show MyDepartment+deriving instance Show MyEmployee++  +Dhall.TH.makeHaskellTypesWith (Dhall.TH.defaultGenerateOptions+    { Dhall.TH.constructorModifier = ("My" <>)+    , Dhall.TH.fieldModifier = ("my" <>) . Data.Text.toTitle+    , Dhall.TH.generateFromDhallInstance = False+    , Dhall.TH.generateToDhallInstance = False+    })+    [ SingleConstructor "MyHKSingle" "HKSingle" "./tests/th/HigherKindSingle.dhall"+    , MultipleConstructors "MyHKUnion" "./tests/th/HigherKindUnion.dhall"+    ]++type MyHKSingle_ = MyHKSingle Maybe Int+type MyHKUnion_ = MyHKUnion Bool Int++deriving instance Eq MyHKSingle_+deriving instance Show MyHKSingle_+deriving instance Dhall.Generic MyHKSingle_+instance Dhall.FromDhall MyHKSingle_+instance Dhall.ToDhall MyHKSingle_++deriving instance Eq MyHKUnion_+deriving instance Show MyHKUnion_+deriving instance Dhall.Generic MyHKUnion_+instance Dhall.FromDhall MyHKUnion_+instance Dhall.ToDhall MyHKUnion_++testMakeHaskellTypesWith :: TestTree+testMakeHaskellTypesWith = Tasty.HUnit.testCase "makeHaskellTypesWith" $ do+    let text0 = "let T = ./tests/th/example.dhall in T.A { x = True, y = [] : List Text }"+        ref0 = MyA{ myX = True, myY = [] }+    myTest text0 ref0++    let text1 = "let T = ./tests/th/example.dhall in T.B (None (List Natural))"+        ref1 = MyB Nothing+    myTest text1 ref1++    let text2 = "let T = ./tests/th/example.dhall in T.C"+        ref2 = MyC+    myTest text2 ref2++    let textDepartment = "let T = ./tests/th/Department.dhall in T.Sales"+        refDepartment = MySales+    myTest textDepartment refDepartment++    let textEmployee = "let T = ./tests/th/Department.dhall in T.Sales"+        refEmployee = MyEmployee{ myName = "", myDepartment = MySales }+    myTest textEmployee refEmployee++    let textHKSingle = "let T = (./tests/th/HigherKindSingle.dhall) Optional Int in T { foo = +1, bar = Some +2, bam = \"\" }"+        refHKSingle = MyHKSingle { myFoo = 1, myBar = Just 2, myBam = "" } :: MyHKSingle_+    myTest textHKSingle refHKSingle++    let textHKUnion0 = "let T = (./tests/th/HigherKindUnion.dhall) Bool Int in T.Foo True"+        refHKUnion0 = MyFoo True :: MyHKUnion_+    myTest textHKUnion0 refHKUnion0++    let textHKUnion1 = "let T = (./tests/th/HigherKindUnion.dhall) Bool Int in T.Bar +1"+        refHKUnion1 = MyBar 1 :: MyHKUnion_+    myTest textHKUnion1 refHKUnion1++    where+        myTest text ref = do+            expr <- Dhall.inputExpr text+            t <- case Dhall.extract Dhall.auto expr of+                Failure e -> throwIO e+                Success t -> return t++            Tasty.HUnit.assertEqual "" t ref+            Tasty.HUnit.assertEqual "" expr $ Dhall.embed Dhall.inject ref++Dhall.TH.makeHaskellTypesWith (Dhall.TH.defaultGenerateOptions+    { Dhall.TH.constructorModifier = ("NoFromDhall" <>)+    , Dhall.TH.fieldModifier = ("noFromDhall" <>) . Data.Text.toTitle+    , Dhall.TH.generateFromDhallInstance = False+    })+    [ MultipleConstructors "NoFromDhallT" "./tests/th/example.dhall"+    ]++instance Dhall.FromDhall NoFromDhallT++Dhall.TH.makeHaskellTypesWith (Dhall.TH.defaultGenerateOptions+    { Dhall.TH.constructorModifier = ("NoToDhall" <>)+    , Dhall.TH.fieldModifier = ("noToDhall" <>) . Data.Text.toTitle+    , Dhall.TH.generateToDhallInstance = False+    })+    [ MultipleConstructors "NoToDhallT" "./tests/th/example.dhall"+    ]++instance Dhall.ToDhall NoToDhallT++Dhall.TH.makeHaskellTypesWith (Dhall.TH.defaultGenerateOptions+    { Dhall.TH.constructorModifier = ("NoInstances" <>)+    , Dhall.TH.fieldModifier = ("noInstances" <>) . Data.Text.toTitle+    , Dhall.TH.generateFromDhallInstance = False+    , Dhall.TH.generateToDhallInstance = False+    })+    [ MultipleConstructors "NoInstancesT" "./tests/th/example.dhall"+    ]++deriving instance Dhall.Generic NoInstancesT+instance Dhall.FromDhall NoInstancesT+instance Dhall.ToDhall NoInstancesT++Dhall.TH.makeHaskellTypesWith (Dhall.TH.defaultGenerateOptions+    { Dhall.TH.constructorModifier = ("Strict" <>)+    , Dhall.TH.fieldModifier = ("strict" <>) . Data.Text.toTitle+    , Dhall.TH.makeStrict = True+    })+    [ MultipleConstructors "StrictFields" "./tests/th/example.dhall"+    ]
+ tests/Dhall/Test/Tags.hs view
@@ -0,0 +1,63 @@+{-# LANGUAGE OverloadedStrings #-}++module Dhall.Test.Tags where++import Data.Text       (Text)+import Dhall.Util      (Input (..))+import System.FilePath ((</>))+import Test.Tasty      (TestTree)++import qualified Data.Text        as Text+import qualified Data.Text.IO     as Text.IO+import qualified Dhall.Tags       as Tags+import qualified Dhall.Test.Util  as Test.Util+import qualified Test.Tasty       as Tasty+import qualified Test.Tasty.HUnit as Tasty.HUnit+import qualified Turtle++tagsDirectory :: FilePath+tagsDirectory = "./tests/tags"++getTests :: IO TestTree+getTests = do+    tagsTests <- Test.Util.discover (Turtle.chars <* ".dhall") tagsTest (Turtle.lstree tagsDirectory)++    let testTree = Tasty.testGroup "tags tests" [ tagsTests, tagsDirTest ]++    return testTree++tagsTest :: Text -> TestTree+tagsTest prefix =+    Tasty.HUnit.testCase (Text.unpack prefix) $ do+        -- The use of toDhallPah is a hack to ensure we always get the same file+        -- paths, i.e. ones with a '.' prefixed and UNIX path separators.+        let inputFile  = Text.unpack (Test.Util.toDhallPath prefix <> ".dhall")+        let outputFile = Text.unpack (prefix <> ".tags")++        actualTags <- fixPathSeparators <$> Tags.generate (InputFile inputFile) Nothing False++        expectedTags <- Text.IO.readFile outputFile++        let message = "The actual tags did not match the expected tags"++        Tasty.HUnit.assertEqual message expectedTags actualTags++tagsDirTest :: TestTree+tagsDirTest =+    Tasty.HUnit.testCase "all" $ do+        let outputFile = Text.unpack . Turtle.format Turtle.fp $ tagsDirectory </> "all.tags"++        actualTags <- fmap fixPathSeparators+                      (Tags.generate+                          (InputFile (Text.unpack . Turtle.format Turtle.fp $ tagsDirectory))+                          (Just [".dhall"])+                          False)++        expectedTags <- Text.IO.readFile outputFile++        let message = "The actual tags did not match the expected tags for directory test"++        Tasty.HUnit.assertEqual message expectedTags actualTags++fixPathSeparators :: Text -> Text+fixPathSeparators = Text.replace "\\" "/"
tests/Dhall/Test/Tutorial.hs view
@@ -6,16 +6,16 @@  import qualified Data.Vector import qualified Dhall-import qualified Dhall.Test.Util as Util+import qualified Dhall.Test.Substitution as Substitution+import qualified Dhall.Test.Util         as Util import qualified Test.Tasty import qualified Test.Tasty.HUnit -import Data.Monoid ((<>))-import Data.Text (Text)-import Dhall (Inject)-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@@ -33,10 +33,20 @@         , Test.Tasty.testGroup "Unions"             [ example 0 "./tests/tutorial/unions0A.dhall" "./tests/tutorial/unions0B.dhall"             , example 1 "./tests/tutorial/unions1A.dhall" "./tests/tutorial/unions1B.dhall"-            , example 2 "./tests/tutorial/unions2A.dhall" "./tests/tutorial/unions2B.dhall"             , example 3 "./tests/tutorial/unions3A.dhall" "./tests/tutorial/unions3B.dhall"             , example 4 "./tests/tutorial/unions4A.dhall" "./tests/tutorial/unions4B.dhall"             ]+        , Test.Tasty.testGroup "Substitutions"+            [ Test.Tasty.HUnit.testCase "substitution1.dhall" $ do+                res <- Substitution.substituteResult "tests/tutorial/substitution1.dhall"+                res @?= Substitution.Failure 1+            , Test.Tasty.HUnit.testCase "substitution2.dhall" $ do+                res <- Substitution.substituteResult "tests/tutorial/substitution2.dhall"+                res @?= Substitution.Failure 1+            , Test.Tasty.HUnit.testCase "substitution3.dhall" $ do+                res <- Substitution.substituteFoo "tests/tutorial/substitution3.dhall"+                res @?= True+            ]         ]  _Interpolation_0 :: TestTree@@ -70,7 +80,7 @@     makeBools True False @?= False )  data Example0 = Example0 { foo :: Bool, bar :: Bool }-    deriving (Generic, Inject)+    deriving (Generic, ToDhall)  _Functions_2 :: TestTree _Functions_2 = Test.Tasty.HUnit.testCase "Example #2" (do
− tests/Dhall/Test/TypeCheck.hs
@@ -1,88 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}--module Dhall.Test.TypeCheck 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 qualified Control.Exception as Exception-import qualified Control.Monad     as Monad-import qualified Data.Text         as Text-import qualified Dhall.Core        as Core-import qualified Dhall.Import      as Import-import qualified Dhall.Parser      as Parser-import qualified Dhall.Test.Util   as Test.Util-import qualified Dhall.TypeCheck   as TypeCheck-import qualified Test.Tasty        as Tasty-import qualified Test.Tasty.HUnit  as Tasty.HUnit-import qualified Turtle--typecheckDirectory :: FilePath-typecheckDirectory = "./dhall-lang/tests/typecheck"--getTests :: IO TestTree-getTests = do-    successTests <- Test.Util.discover (Turtle.chars <* "A.dhall") successTest (Turtle.lstree (typecheckDirectory </> "success"))--    let failureTestFiles = do-            path <- Turtle.lstree (typecheckDirectory </> "failure")--            let skip =-                    [ typecheckDirectory </> "failure/duplicateFields.dhall"-                    ]--            Monad.guard (path `notElem` skip)--            return path--    failureTests <- Test.Util.discover (Turtle.chars <> ".dhall") failureTest failureTestFiles--    let testTree = Tasty.testGroup "typecheck tests"-            [ successTests-            , failureTests-            ]--    return testTree--successTest :: Text -> TestTree-successTest prefix =-    Tasty.HUnit.testCase (Text.unpack prefix) $ do-        let actualCode   = Test.Util.toDhallPath (prefix <> "A.dhall")-        let expectedCode = Test.Util.toDhallPath (prefix <> "B.dhall")--        actualExpr <- Core.throws (Parser.exprFromText mempty actualCode)--        expectedExpr <- Core.throws (Parser.exprFromText mempty expectedCode)--        let annotatedExpr = Core.Annot actualExpr expectedExpr--        resolvedExpr <- Import.load annotatedExpr--        _ <- Core.throws (TypeCheck.typeOf resolvedExpr)--        return ()--failureTest :: Text -> TestTree-failureTest path = do-    Tasty.HUnit.testCase (Text.unpack path) $ do-        let dhallPath = Test.Util.toDhallPath path--        expression <- Core.throws (Parser.exprFromText mempty dhallPath)--        let io :: IO Bool-            io = do-                _ <- Import.load expression-                return True--        let handler :: SomeException -> IO Bool-            handler _ = return False--        typeChecked <- Exception.handle handler io--        if typeChecked-            then fail (Text.unpack path <> " should not have type-checked")-            else return ()
+ tests/Dhall/Test/TypeInference.hs view
@@ -0,0 +1,127 @@+{-# LANGUAGE CPP               #-}+{-# LANGUAGE OverloadedStrings #-}++module Dhall.Test.TypeInference where++import Control.Exception (SomeException (..))+import Data.Text         (Text)+import System.FilePath   ((</>))+import Test.Tasty        (TestTree)++import qualified Control.Exception as Exception+import qualified Data.Text         as Text+import qualified Data.Text.IO      as Text.IO+import qualified Dhall.Core        as Core+import qualified Dhall.Import      as Import+import qualified Dhall.Parser      as Parser+import qualified Dhall.Test.Util   as Test.Util+import qualified Dhall.TypeCheck   as TypeCheck+import qualified System.FilePath   as FilePath+import qualified Test.Tasty        as Tasty+import qualified Test.Tasty.HUnit  as Tasty.HUnit+import qualified Turtle++typeInferenceDirectory :: FilePath+typeInferenceDirectory = "./dhall-lang/tests/type-inference"++getTests :: IO TestTree+getTests = do+    let successTestFiles = do+            path <- Turtle.lstree (typeInferenceDirectory </> "success")++            let skip =+                    -- These tests intermittently fails with:+                    -- "Error: Remote host not found"+                    [ typeInferenceDirectory </> "success/CacheImportsA.dhall"+                    , typeInferenceDirectory </> "success/CacheImportsCanonicalizeA.dhall"+                    ]++            path `Test.Util.pathNotIn` skip++            return path++    successTests <- Test.Util.discover (Turtle.chars <* "A.dhall") successTest successTestFiles++    let failureTestFiles = Turtle.lstree (typeInferenceDirectory </> "failure")++    failureTests <- Test.Util.discover (Turtle.chars <* ".dhall") failureTest failureTestFiles++    let testTree = Tasty.testGroup "type-inference tests"+            [ successTests+            , failureTests+            ]++    return testTree++successTest :: Text -> TestTree+successTest prefix = do+    let expectedFailures =+                []+#if defined(WITH_HTTP) && defined(NETWORK_TESTS)+#else+            ++  [ typeInferenceDirectory </> "success/CacheImports"+                ]+#endif++    Test.Util.testCase prefix expectedFailures $ do+        let prefixFP = Text.unpack prefix++        actualCode <- Text.IO.readFile (prefixFP <> "A.dhall")++        actualExpr <- Core.throws (Parser.exprFromText mempty actualCode)++        tryResolvedExpr <-+            Exception.try+               (Test.Util.loadRelativeTo+                   (FilePath.takeDirectory prefixFP)+                   Import.IgnoreSemanticCache+                   (Core.denote actualExpr))++        resolvedExpr <- case tryResolvedExpr of+            Left  exception    -> Tasty.HUnit.assertFailure (show (exception :: SomeException))+            Right resolvedExpr -> return resolvedExpr++        expectedTypeCode <- Text.IO.readFile (prefixFP <> "B.dhall")++        expectedType <- Core.throws (Parser.exprFromText mempty expectedTypeCode)++        resolvedExpectedType <- Import.assertNoImports (Core.denote expectedType)++        inferredType <- case TypeCheck.typeOf resolvedExpr of+            Left  exception    -> Tasty.HUnit.assertFailure (show exception)+            Right inferredType -> return inferredType++        let message = "The inferred type did not match the expected type"++        Tasty.HUnit.assertEqual message resolvedExpectedType inferredType++        -- We also add this to exercise the `Dhall.Eval.conv` code path, since+        -- it's easy to forget to update it when adding new syntax+        _ <- Core.throws (TypeCheck.typeOf (Core.Annot resolvedExpr resolvedExpectedType))+        return ()++failureTest :: Text -> TestTree+failureTest prefix = do+    let expectedFailures =+               [+               -- Duplicate fields are incorrectly caught during parsing:+               -- https://github.com/dhall-lang/dhall-haskell/issues/772+                 typeInferenceDirectory </> "failure/unit/RecordTypeDuplicateFields"+               , typeInferenceDirectory </> "failure/unit/UnionTypeDuplicateVariants1"+               , typeInferenceDirectory </> "failure/unit/UnionTypeDuplicateVariants2"+               ]++    Test.Util.testCase prefix expectedFailures $ do+        let prefixFP = Text.unpack prefix++        code <- Text.IO.readFile (prefixFP <> ".dhall")++        expression <- case Parser.exprFromText mempty code of+            Left _ -> Tasty.HUnit.assertFailure (prefixFP <> " should have parsed")+            Right e -> return e++        resolved <- Import.assertNoImports expression++        case TypeCheck.typeOf resolved of+            Left  _ -> return ()+            Right _ -> Tasty.HUnit.assertFailure (prefixFP <> " should not have type-checked")
tests/Dhall/Test/Util.hs view
@@ -1,83 +1,271 @@+{-# LANGUAGE CPP               #-}+{-# LANGUAGE NamedFieldPuns    #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RankNTypes        #-}+{-# LANGUAGE ViewPatterns      #-}  module Dhall.Test.Util     ( code     , codeWith     , equivalent+    , load+    , loadRelativeTo+    , loadWith     , normalize'     , normalizeWith'     , assertNormalizesTo     , assertNormalizesToWith     , assertNormalized     , assertTypeChecks+    , assertDoesntTypeCheck     , discover+    , Dhall.Test.Util.testCase+    , pathIn+    , pathNotIn+    , pathNotPrefixOf+    , pathNotSuffixOf     , toDhallPath+    , managedTestEnvironment     ) where -import Data.Bifunctor (first)-import Data.Text (Text)-import Dhall.Context (Context)-import Dhall.Core (Expr, Normalizer, ReifiedNormalizer(..))-import Dhall.Parser (Src)-import Dhall.TypeCheck (X)-import Prelude hiding (FilePath)+import Control.Applicative              (Alternative, liftA2, (<|>))+import Control.Exception                (tryJust)+import Control.Monad                    (guard)+import Control.Monad.Trans.State.Strict (StateT)+import Data.Bifunctor                   (first)+import Data.Text                        (Text)+import Data.Void                        (Void)+import Dhall.Context                    (Context)+import Dhall.Core+    ( Chunks (..)+    , Expr (..)+    , Import+    , Normalizer+    , ReifiedNormalizer (..)+    )+import Dhall.Import                     (SemanticCacheMode (..), Status (..))+import Dhall.Parser                     (Src)+import System.IO.Error                  (isDoesNotExistError)+import Test.Tasty                       (TestTree) import Test.Tasty.HUnit-import 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.Foldl                    as Foldl+import qualified Control.Monad.Trans.State.Strict as State import qualified Data.Functor-import qualified Data.Text         as Text+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 Test.Tasty        as Tasty+import qualified System.FilePath                  as FilePath+import qualified Test.Tasty                       as Tasty+import qualified Test.Tasty.ExpectedFailure       as Tasty.ExpectedFailure import qualified Turtle -normalize' :: Expr Src X -> Text+#if defined(WITH_HTTP) && defined(NETWORK_TESTS)+import qualified Data.Foldable+#else+import Control.Monad.IO.Class (MonadIO (..))+import Dhall.Core             (Directory (..), File (..), URL (..))+import Lens.Micro.Mtl         (zoom)++import qualified Data.Foldable+import qualified Data.Text.Encoding+import qualified Data.Text.IO+#endif++normalize' :: Expr Src Void -> Text normalize' = Dhall.Core.pretty . Dhall.Core.normalize -normalizeWith' :: Normalizer X -> Expr Src X -> Text+normalizeWith' :: Normalizer Void -> Expr Src Void -> Text normalizeWith' ctx t =   Dhall.Core.pretty (Dhall.Core.normalizeWith (Just (ReifiedNormalizer ctx)) t) -code :: Text -> IO (Expr Src X)+code :: Text -> IO (Expr Src Void) code = codeWith Dhall.Context.empty -codeWith :: Context (Expr Src X) -> Text -> IO (Expr Src X)+codeWith :: Context (Expr Src Void) -> Text -> IO (Expr Src Void) codeWith ctx expr = do     expr0 <- case Dhall.Parser.exprFromText mempty expr of         Left parseError -> Control.Exception.throwIO parseError         Right expr0     -> return expr0-    expr1 <- Dhall.Import.load expr0+    expr1 <- load expr0     case Dhall.TypeCheck.typeWith ctx expr1 of         Left typeError -> Control.Exception.throwIO typeError         Right _        -> return ()     return expr1 +load :: Expr Src Import -> IO (Expr Src Void)+load = loadRelativeTo "." UseSemanticCache++loadRelativeTo :: FilePath.FilePath -> SemanticCacheMode -> Expr Src Import -> IO (Expr Src Void)+loadRelativeTo rootDirectory semanticCacheMode expression =+    State.evalStateT+        (loadWith expression)+        (Dhall.Import.emptyStatus rootDirectory) { _semanticCacheMode = semanticCacheMode }++#if defined(WITH_HTTP) && defined(NETWORK_TESTS)+loadWith :: Expr Src Import -> StateT Status IO (Expr Src Void)+loadWith = Dhall.Import.loadWith++#else+loadWith :: Expr Src Import -> StateT Status IO (Expr Src Void)+loadWith expr = do+    zoom Dhall.Import.remote (State.put mockRemote)+    Dhall.Import.loadWith expr++mockRemote :: Dhall.Core.URL -> StateT Status IO Data.Text.Text+mockRemote+    url@URL+        { authority = "raw.githubusercontent.com"+        , path = File (Directory components) file+        } = do+    let localDir = case reverse components of+            "dhall-lang" : "dhall-lang" : _ : rest ->+                reverse ("dhall-lang" : rest)+            "Nadrieril" : "dhall-rust" : _ : "dhall" : rest ->+                reverse ("dhall-lang" : rest)+            _ -> do+                fail ("Unable to mock URL: " <> Text.unpack (Dhall.Core.pretty url))++    localPath <- Dhall.Import.localToPath Dhall.Core.Here (File (Directory localDir) file)++    liftIO (Data.Text.IO.readFile localPath)++mockRemote+    URL { authority = "prelude.dhall-lang.org"+        , path = File (Directory components) file+        } = do+    let localDir = components ++ [ "Prelude", "dhall-lang" ]++    localPath <- Dhall.Import.localToPath Dhall.Core.Here (File (Directory localDir) file)++    liftIO (Data.Text.IO.readFile localPath)++mockRemote url@URL{ authority = "test.dhall-lang.org", path, headers } =+    case (path, fmap Dhall.Import.toHeaders headers) of+        (File (Directory []) "foo", Just [("test", _)]) ->+            return "./bar"+        (File (Directory []) "bar", Just [("test", _)]) ->+            return "True"+        (File (Directory ["cors"]) "AllowedAll.dhall", _) ->+            return "42"+        (File (Directory ["cors"]) "OnlyGithub.dhall", _) ->+            return "42"+        (File (Directory ["cors"]) "OnlySelf.dhall", _) ->+            return "42"+        (File (Directory ["cors"]) "OnlyOther.dhall", _) ->+            return "42"+        (File (Directory ["cors"]) "Empty.dhall", _) ->+            return "42"+        (File (Directory ["cors"]) "NoCORS.dhall", _) ->+            return "42"+        (File (Directory ["cors"]) "Null.dhall", _) ->+            return "42"+        (File (Directory ["cors"]) "SelfImportAbsolute.dhall", _) ->+            return "https://test.dhall-lang.org/cors/NoCORS.dhall"+        (File (Directory ["cors"]) "SelfImportRelative.dhall", _) ->+            return "./NoCORS.dhall"+        (File (Directory ["cors"]) "TwoHopsFail.dhall", _) ->+            return "https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/OnlySelf.dhall"+        (File (Directory ["cors"]) "TwoHopsSuccess.dhall", _) ->+            return "https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/OnlyGithub.dhall"+        _ -> do+            fail ("Unable to mock URL: " <> Text.unpack (Dhall.Core.pretty url))++mockRemote url@URL{ authority = "httpbin.org", path, headers } =+    case (path, fmap Dhall.Import.toHeaders headers) of+        (File (Directory []) "user-agent", Just [("user-agent", userAgent)]) -> do+            let agentText = Data.Text.Encoding.decodeUtf8 userAgent++            return ("{\n  \"user-agent\": \"" <> agentText <> "\"\n}\n")+        (File (Directory []) "user-agent", Nothing) -> do+            return ("{\n  \"user-agent\": \"Dhall\"\n}\n")+        _ -> do+            fail ("Unable to mock URL: " <> Text.unpack (Dhall.Core.pretty url))++mockRemote url = do+    let urlString = Text.unpack (Dhall.Core.pretty url)+    fail ("(mock http) Url does not match any of the hard-coded rules: "+        <> urlString)+#endif++{- Given a test prefix, returns a managed resource+   which sets / reverts relevant environment variables based+   on `prefix <> "ENV.dhall"` (if present)+ -}+managedTestEnvironment :: Text -> Turtle.Managed [(Text, Maybe Text)]+managedTestEnvironment prefix = Turtle.managed (Control.Exception.bracket setup cleanup)+  where+    envPath = Text.unpack (prefix <> "ENV.dhall")++    setup :: IO [(Text, Maybe Text)]+    setup = do+        envFileContents <-+            tryJust (guard . isDoesNotExistError) (Text.IO.readFile envPath)++        testEnv <- case envFileContents of+            Right contents -> do+                resolved <- code contents+                return (convertEnvExpr (Dhall.Core.normalize resolved))+            Left _ -> return []++        traverse setEnv testEnv++    cleanup :: [(Text, Maybe Text)] -> IO ()+    cleanup = Data.Foldable.traverse_ restoreEnv++    convertEnvExpr :: Expr Src Void -> [(Text, Text)]+    convertEnvExpr (ListLit _ hs) = Data.Foldable.toList (Data.Foldable.fold maybePairs)+      where+          maybePairs = mapM toPair hs++          toPair :: Expr s a -> Maybe (Text, Text)+          toPair (RecordLit m) = do+              (Dhall.Core.recordFieldValue -> TextLit (Chunks [] key), Dhall.Core.recordFieldValue -> TextLit (Chunks [] value))+                  <- lookupHeader <|> lookupMapKey+              return (key, value)+                where+                  lookupHeader = liftA2 (,) (Dhall.Map.lookup "header" m) (Dhall.Map.lookup "value" m)+                  lookupMapKey = liftA2 (,) (Dhall.Map.lookup "mapKey" m) (Dhall.Map.lookup "mapValue" m)+          toPair _ = Nothing+    convertEnvExpr _ = []++    setEnv :: (Text, Text) -> IO (Text, Maybe Text)+    setEnv (k, v) = do+        old <- Turtle.need k+        Turtle.export k v+        return (k, old)++    restoreEnv :: (Text, Maybe Text) -> IO ()+    restoreEnv (k, Just old) = Turtle.export k old+    restoreEnv (k, Nothing) = Turtle.unset k+ equivalent :: Text -> Text -> IO () equivalent text0 text1 = do-    expr0 <- fmap Dhall.Core.normalize (code text0) :: IO (Expr X X)-    expr1 <- fmap Dhall.Core.normalize (code text1) :: IO (Expr X X)+    expr0 <- fmap Dhall.Core.normalize (code text0) :: IO (Expr Void Void)+    expr1 <- fmap Dhall.Core.normalize (code text1) :: IO (Expr Void Void)     assertEqual "Expressions are not equivalent" expr0 expr1 -assertNormalizesTo :: Expr Src X -> Text -> IO ()+assertNormalizesTo :: Expr Src Void -> Text -> IO () assertNormalizesTo e expected = do   assertBool msg (not $ Dhall.Core.isNormalized e)   normalize' e @?= expected   where msg = "Given expression is already in normal form" -assertNormalizesToWith :: Normalizer X -> Expr Src X -> Text -> IO ()+assertNormalizesToWith :: Normalizer Void -> Expr Src Void -> Text -> IO () assertNormalizesToWith ctx e expected = do   assertBool msg (not $ Dhall.Core.isNormalizedWith ctx (first (const ()) e))   normalizeWith' ctx e @?= expected   where msg = "Given expression is already in normal form" -assertNormalized :: Expr Src X -> IO ()+assertNormalized :: Expr Src Void -> IO () assertNormalized e = do   assertBool msg1 (Dhall.Core.isNormalized e)   assertEqual msg2 (normalize' e) (Dhall.Core.pretty e)@@ -87,15 +275,25 @@ assertTypeChecks :: Text -> IO () assertTypeChecks text = Data.Functor.void (code text) +assertDoesntTypeCheck :: Text -> IO ()+assertDoesntTypeCheck text = do+    expr0 <- case Dhall.Parser.exprFromText mempty text of+        Left parseError -> Control.Exception.throwIO parseError+        Right e         -> return e+    expr1 <- load expr0+    case Dhall.TypeCheck.typeOf expr1 of+        Left _      -> return ()+        Right type_ -> fail ("Bad type for " <> Text.unpack text <> "\n  " <> show type_)+ {-| Automatically run a test on all files in a directory tree that end in     @A.dhall@ -} discover :: Pattern Text -> (Text -> TestTree) -> Shell FilePath -> IO TestTree discover pattern buildTest paths = do     let shell = do-            path <- paths+            path_ <- paths -            let pathText = Turtle.format fp path+            let pathText = Turtle.format fp (FilePath.normalise path_)              prefix : _ <- return (Turtle.match pattern pathText) @@ -105,10 +303,31 @@      return (Tasty.testGroup "discover" tests) +testCase :: Text -> [ FilePath ] -> Assertion -> TestTree+testCase prefix expectedFailures assertion =+    if prefix `elem` map (Turtle.format fp . FilePath.normalise) expectedFailures+    then Tasty.ExpectedFailure.expectFail test+    else test+  where+    test = Test.Tasty.HUnit.testCase (Text.unpack prefix) assertion +pathIn :: Alternative f => FilePath -> [FilePath] -> f ()+pathIn this = guard . any (FilePath.equalFilePath this)++pathNotIn :: Alternative f => FilePath -> [FilePath] -> f ()+pathNotIn this = guard . not . any (FilePath.equalFilePath this)++pathNotPrefixOf :: Alternative f => FilePath -> FilePath -> f ()+pathNotPrefixOf this =+    guard . not . List.isPrefixOf (FilePath.normalise this) . FilePath.normalise++pathNotSuffixOf :: Alternative f => FilePath -> FilePath -> f ()+pathNotSuffixOf this =+    guard . not . List.isSuffixOf (FilePath.normalise this) . FilePath.normalise+ {-| Path names on Windows are not valid Dhall paths due to using backslashes     instead of forwardslashes to separate path components.  This utility fixes     them if necessary -} toDhallPath :: Text -> Text-toDhallPath = Text.replace "\\" "/"+toDhallPath = ("./" <>) . Text.replace "\\" "/"
+ tests/diff/appList.txt view
@@ -0,0 +1,4 @@+  λ(… :   …+        → …)+→ …+  …
+ tests/diff/appListA.dhall view
@@ -0,0 +1,1 @@+λ(f : List Bool -> Bool) → f ([] : List Bool)
+ tests/diff/appListB.dhall view
@@ -0,0 +1,1 @@+λ(f : List Bool -> Bool) → f ([] : List Bool)
+ tests/diff/emptyList.txt view
@@ -0,0 +1,2 @@+- [] : …++ True
+ tests/diff/emptyListA.dhall view
@@ -0,0 +1,1 @@+[] : List Natural
+ tests/diff/emptyListB.dhall view
@@ -0,0 +1,1 @@+True
+ tests/diff/function.txt view
@@ -0,0 +1,6 @@+  …+→ …+→ …@- 1+    + 0++→ …
+ tests/diff/functionA.dhall view
@@ -0,0 +1,1 @@+∀(a : Type) → ∀(b : Type) → ∀(x : a) → Bool
+ tests/diff/functionB.dhall view
@@ -0,0 +1,1 @@+∀(a : Type) → ∀(b : Type) → ∀(x : b) → Bool
+ tests/diff/insideList.txt view
@@ -0,0 +1,7 @@+[ …+, { y = - 4+        + 5+  , …+  }+]+
+ tests/diff/insideListA.dhall view
@@ -0,0 +1,3 @@+[ { x = 1, y = 2 }+, { x = 3, y = 4 }+]
+ tests/diff/insideListB.dhall view
@@ -0,0 +1,3 @@+[ { x = 1, y = 2 }+, { x = 3, y = 5 }+]
+ tests/diff/nonEmptyList.txt view
@@ -0,0 +1,2 @@+- [ … ]++ True
+ tests/diff/nonEmptyListA.dhall view
@@ -0,0 +1,1 @@+[1]
+ tests/diff/nonEmptyListB.dhall view
@@ -0,0 +1,1 @@+True
+ tests/diff/with.txt view
@@ -0,0 +1,5 @@+  λ(… : { …+        })+→ … with …+ .c.d+         = - 2+           + 3
+ tests/diff/withA.dhall view
@@ -0,0 +1,1 @@+λ(r : { a : Natural }) → r with b = 2
+ tests/diff/withB.dhall view
@@ -0,0 +1,1 @@+λ(r : { a : Natural }) → r with b.c.d = 3
+ tests/format/applicationMultilineA.dhall view
@@ -0,0 +1,33 @@+{ app =+    ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff+      aaaaaaaaaaaaaaaaa+, app2 =+    f+      a+      b+      cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc+, app3 =+    f+      a+      b+      c+      dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd+, some =+    Some+      aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+, someList =+    Some+      [ aaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbb, cccccccccccccccccccccccc, dddddddddddddd ]+, merge1 =+    merge+      aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+      bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb+, merge3 =+    merge+      a+      b+      ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc+, toMap1 =+    toMap+      aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+}
+ tests/format/applicationMultilineB.dhall view
@@ -0,0 +1,34 @@+{ app =+    ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff+      aaaaaaaaaaaaaaaaa+, app2 =+    f+      a+      b+      cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc+, app3 =+    f+      a+      b+      c+      dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd+, some = Some+    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+, someList = Some+  [ aaaaaaaaaaaaaaaaaaaaaaaaaa+  , bbbbbbbbbbbbbbbbbbbb+  , cccccccccccccccccccccccc+  , dddddddddddddd+  ]+, merge1 =+    merge+      aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+      bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb+, merge3 =+    merge+      a+      b+      ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc+, toMap1 = toMap+    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+}
tests/format/asciiB.dhall view
+ tests/format/concatSepA.dhall view
@@ -0,0 +1,30 @@+{-+Concatenate a `List` of `Text` values with a separator in between each value+-}+let Status = < Empty | NonEmpty : Text >++let concatSep+    : ∀(separator : Text) → ∀(elements : List Text) → Text+    =   λ(separator : Text)+      → λ(elements : List Text)+      → let status =+              List/fold Text elements Status+                (   λ(element : Text)+                  → λ(status : Status)+                  → merge+                      { Empty = Status.NonEmpty element+                      , NonEmpty =+                            λ(result : Text)+                          → Status.NonEmpty (element ++ separator ++ result)+                      }+                      status+                )+                Status.Empty+        +        in  merge { Empty = "", NonEmpty = λ(result : Text) → result } status++let example0 = assert : concatSep ", " [ "ABC", "DEF", "GHI" ] ≡ "ABC, DEF, GHI"++let example1 = assert : concatSep ", " ([] : List Text) ≡ ""++in  concatSep
+ tests/format/concatSepB.dhall view
@@ -0,0 +1,33 @@+{-+Concatenate a `List` of `Text` values with a separator in between each value+-}+let Status = < Empty | NonEmpty : Text >++let concatSep+    : ∀(separator : Text) → ∀(elements : List Text) → Text+    = λ(separator : Text) →+      λ(elements : List Text) →+        let status =+              List/fold+                Text+                elements+                Status+                ( λ(element : Text) →+                  λ(status : Status) →+                    merge+                      { Empty = Status.NonEmpty element+                      , NonEmpty =+                          λ(result : Text) →+                            Status.NonEmpty (element ++ separator ++ result)+                      }+                      status+                )+                Status.Empty++        in  merge { Empty = "", NonEmpty = λ(result : Text) → result } status++let example0 = assert : concatSep ", " [ "ABC", "DEF", "GHI" ] ≡ "ABC, DEF, GHI"++let example1 = assert : concatSep ", " ([] : List Text) ≡ ""++in  concatSep
+ tests/format/dottedFieldsA.dhall view
@@ -0,0 +1,1 @@+{ x = { y = { a = { b = 1 }, c = { d = 2 } } } }
+ tests/format/dottedFieldsB.dhall view
@@ -0,0 +1,1 @@+{ x.y = { a.b = 1, c.d = 2 } }
+ tests/format/dottedFieldsCommentsA.dhall view
@@ -0,0 +1,17 @@+{   {- A -}+    a+    -- B+  . -- C+    b+  . c+    {- D -}+  . d =+      -- E+      x+,   {- F -}+    e+    {- G -}+  . f =+      {- H -}+      { g = y }+}
+ tests/format/dottedFieldsCommentsB.dhall view
@@ -0,0 +1,17 @@+{   {- A -}+    a+    -- B+  . -- C+    b+  . c+    {- D -}+  . d+  = -- E+    x+,   {- F -}+    e+    {- G -}+  . f+  = {- H -}+    { g = y }+}
tests/format/doubleRoundB.dhall view
@@ -1,37 +1,37 @@-[ 1.0-, 1.0-, 1.0000000000000002+[ 1.0000000000000000+, 1.0000000000000001 , 1.0000000000000002-, 1.0000000000000004+, 1.0000000000000003 , 1.0000000000000004-, 1.0000000000000007+, 1.0000000000000005+, 1.0000000000000006 , 1.0000000000000007-, 1.0000000000000009+, 1.0000000000000008 , 1.0000000000000009-, 1.0e64-, 1.0000000000000002e64+, 1.0000000000000000e64+, 1.0000000000000001e64 , 1.0000000000000002e64 , 1.0000000000000003e64-, 1.0000000000000005e64+, 1.0000000000000004e64 , 1.0000000000000005e64 , 1.0000000000000006e64-, 1.0000000000000008e64+, 1.0000000000000007e64 , 1.0000000000000008e64 , 1.0000000000000009e64-, 1.0e100-, 1.0e100-, 1.0000000000000002e100+, 1.0000000000000000e100+, 1.0000000000000001e100 , 1.0000000000000002e100-, 1.0000000000000004e100+, 1.0000000000000003e100 , 1.0000000000000004e100+, 1.0000000000000005e100 , 1.0000000000000006e100-, 1.0000000000000008e100+, 1.0000000000000007e100 , 1.0000000000000008e100-, 1.000000000000001e100-, 1.7976931348623157e308-, 1.7976931348623157e308-, 1.7976931348623155e308-, -1.7976931348623157e308-, -1.7976931348623157e308-, -1.7976931348623155e308+, 1.0000000000000009e100+, 179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497791.0+, 179769313486231560835325876058105298516207002341652166261661174625869553267292326574530099287946549246750631490335877017522087105926987962906277604735569213290190919152394180476217125334960946356387261286640198029037799514183602981511756283727771403830521483963923935633133642802139091669457927874464075218945.0+, 179769313486231560835325876058105298516207002341652166261661174625869553267292326574530099287946549246750631490335877017522087105926987962906277604735569213290190919152394180476217125334960946356387261286640198029037799514183602981511756283727771403830521483963923935633133642802139091669457927874464075218944.0+, -179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497791.0+, -179769313486231560835325876058105298516207002341652166261661174625869553267292326574530099287946549246750631490335877017522087105926987962906277604735569213290190919152394180476217125334960946356387261286640198029037799514183602981511756283727771403830521483963923935633133642802139091669457927874464075218945.0+, -179769313486231560835325876058105298516207002341652166261661174625869553267292326574530099287946549246750631490335877017522087105926987962906277604735569213290190919152394180476217125334960946356387261286640198029037799514183602981511756283727771403830521483963923935633133642802139091669457927874464075218944.0 ]
+ tests/format/duplicatesA.dhall view
@@ -0,0 +1,4 @@+{ {- Comments around duplicate fields are not preserved -} foo.bar = 1+, foo = { baz = {- Comments within values are still preserved-} 2 }+, foo = qux+}
+ tests/format/duplicatesB.dhall view
@@ -0,0 +1,6 @@+{ foo.bar = 1+, foo.baz+  = {- Comments within values are still preserved-}+    2+, foo = qux+}
tests/format/emptyRecordB.dhall view
+ tests/format/envVarsA.dhall view
@@ -0,0 +1,1 @@+[ env:x, env:"1", env:" ", env:"\\", env:"." ]
+ tests/format/envVarsB.dhall view
@@ -0,0 +1,1 @@+[ env:x, env:"1", env:" ", env:"\\", env:"." ]
tests/format/escapeNumericLabelB.dhall view
tests/format/escapeSingleQuotedOpenInterpolationB.dhall view
tests/format/fieldOrderB.dhall view
+ tests/format/functionLikeA.dhall view
@@ -0,0 +1,6 @@+{ example0 = merge a b + merge a b+, example1 = (merge a b : T) + (merge a b : T)+, example2 = toMap a + toMap a+, example3 = (toMap a b : T) + (toMap a b : T)+, example4 = Some a + Some a+}
+ tests/format/functionLikeB.dhall view
@@ -0,0 +1,6 @@+{ example0 = merge a b + merge a b+, example1 = (merge a b : T) + (merge a b : T)+, example2 = toMap a + toMap a+, example3 = (toMap a b : T) + (toMap a b : T)+, example4 = Some a + Some a+}
+ tests/format/headerA.dhall view
@@ -0,0 +1,4 @@+   +{- bla -} +  +True
+ tests/format/headerB.dhall view
@@ -0,0 +1,2 @@+{- bla -}+True
+ tests/format/headerNoNewlineA.dhall view
@@ -0,0 +1,1 @@+{- -}0
+ tests/format/headerNoNewlineB.dhall view
@@ -0,0 +1,2 @@+{- -}+0
tests/format/ifThenElseB.dhall view
@@ -1,13 +1,7 @@-      if True-+if    True then  if True then if True then 1 else 2 else if True then 3 else 4- else  if True- then  if True then 5 else 6- else  if True- then  7- else  8
tests/format/importAccessB.dhall view
+ tests/format/importAltPrecedenceA.dhall view
@@ -0,0 +1,1 @@+a ? b || c
+ tests/format/importAltPrecedenceB.dhall view
@@ -0,0 +1,1 @@+a ? b || c
tests/format/importLines2A.dhall view
tests/format/importLines2B.dhall view
tests/format/importLinesB.dhall view
tests/format/importSuffixB.dhall view
+ tests/format/innerMultilineA.dhall view
@@ -0,0 +1,11 @@+{ inner =+  ''++  one++  two++  three++  ''+}
+ tests/format/innerMultilineB.dhall view
@@ -0,0 +1,11 @@+{ inner =+    ''++    one++    two++    three++    ''+}
+ tests/format/interpolation0A.dhall view
@@ -0,0 +1,1 @@+"foo\n${a} bar"
+ tests/format/interpolation0B.dhall view
@@ -0,0 +1,3 @@+''+foo+${a} bar''
+ tests/format/ipfsA.dhall view
@@ -0,0 +1,163 @@+let name = "ipfs"++let labels =+      { `app.kubernetes.io/name` = name+      , `app.kubernetes.io/instance` = "wintering-rodent"+      , `app.kubernetes.io/version` = "0.4.0"+      , `app.kubernetes.io/managed-by` = "dhall"+      }++let matchLabels =+      labels.{ `app.kubernetes.io/name`, `app.kubernetes.io/instance` }++let k8s =+      https://raw.githubusercontent.com/dhall-lang/dhall-kubernetes/4ab28225a150498aef67c226d3c5f026c95b5a1e/package.dhall sha256:2c7ac35494f16b1f39afcf3467b2f3b0ab579edb0c711cddd2c93f1cbed358bd++let serviceName = "ipfs"++let apiPort = k8s.IntOrString.Int 5001++let gatewayPort = k8s.IntOrString.Int 8080++let toRule =+        λ ( args+          : { host : Text+            , path : Text+            , serviceName : Text+            , servicePort : k8s.IntOrString+            }+          )+      → k8s.IngressRule::{+        , host = Some args.host+        , http =+            Some+              k8s.HTTPIngressRuleValue::{+              , paths =+                  [ k8s.HTTPIngressPath::{+                    , path = Some args.path+                    , backend =+                        k8s.IngressBackend::args.{ serviceName, servicePort }+                    }+                  ]+              }+        }++in  [ k8s.Resource.Ingress+        k8s.Ingress::{+        , metadata =+            k8s.ObjectMeta::{ labels = toMap labels, name = "${name}-api" }+        , spec =+            Some+              k8s.IngressSpec::{+              , rules =+                  [ toRule+                      { host = "localhost"+                      , path = "/"+                      , serviceName = serviceName+                      , servicePort = gatewayPort+                      }+                  , toRule+                      { host = "localhost"+                      , path = "/"+                      , serviceName = serviceName+                      , servicePort = apiPort+                      }+                  ]+              }+        }+    , k8s.Resource.Service+        k8s.Service::{+        , metadata =+            k8s.ObjectMeta::{ name = serviceName, labels = toMap labels }+        , spec =+            Some+              k8s.ServiceSpec::{+              , ports =+                  [ k8s.ServicePort::{+                    , port = 5001+                    , targetPort = Some apiPort+                    , name = Some "api"+                    }+                  , k8s.ServicePort::{+                    , port = 8080+                    , targetPort = Some gatewayPort+                    , name = Some "api"+                    }+                  ]+              , selector = toMap matchLabels+              }+        }+    , k8s.Resource.StatefulSet+        k8s.StatefulSet::{+        , metadata = k8s.ObjectMeta::{ name = name, labels = toMap labels }+        , spec =+            Some+              k8s.StatefulSetSpec::{+              , serviceName = serviceName+              , selector =+                  k8s.LabelSelector::{ matchLabels = toMap matchLabels }+              , template =+                  k8s.PodTemplateSpec::{+                  , metadata =+                      k8s.ObjectMeta::{ name = name, labels = toMap labels }+                  , spec =+                      Some+                        k8s.PodSpec::{+                        , securityContext =+                            Some+                              k8s.PodSecurityContext::{+                              , runAsUser = Some 1000+                              , runAsGroup = Some 1000+                              , fsGroup = Some 1000+                              }+                        , containers =+                            [ k8s.Container::{+                              , name = name+                              , image = Some "ipfs/go-ipfs:v0.4.22"+                              , livenessProbe =+                                  k8s.Probe::{+                                  , httpGet =+                                      Some+                                        k8s.HTTPGetAction::{+                                        , path =+                                            Some "/debug/metrics/prometheus"+                                        , port = k8s.IntOrString.String "api"+                                        }+                                  , initialDelaySeconds = Some 15+                                  , periodSeconds = Some 3+                                  }+                              , readinessProbe =+                                  k8s.Probe::{+                                  , httpGet =+                                      Some+                                        k8s.HTTPGetAction::{+                                        , path =+                                            Some "/debug/metrics/prometheus"+                                        , port = k8s.IntOrString.String "api"+                                        }+                                  , initialDelaySeconds = Some 15+                                  , periodSeconds = Some 3+                                  }+                              , ports =+                                  [ k8s.ContainerPort::{+                                    , containerPort = 5001+                                    , name = Some "api"+                                    }+                                  , k8s.ContainerPort::{+                                    , containerPort = 8080+                                    , name = Some "gateway"+                                    }+                                  ]+                              , volumeMounts =+                                  [ k8s.VolumeMount::{+                                    , name = "ipfs-storage"+                                    , mountPath = "/data/ipfs"+                                    }+                                  ]+                              }+                            ]+                        }+                  }+              }+        }+    ]
+ tests/format/ipfsB.dhall view
@@ -0,0 +1,144 @@+let name = "ipfs"++let labels =+      { `app.kubernetes.io/name` = name+      , `app.kubernetes.io/instance` = "wintering-rodent"+      , `app.kubernetes.io/version` = "0.4.0"+      , `app.kubernetes.io/managed-by` = "dhall"+      }++let matchLabels =+      labels.{ `app.kubernetes.io/name`, `app.kubernetes.io/instance` }++let k8s =+      https://raw.githubusercontent.com/dhall-lang/dhall-kubernetes/4ab28225a150498aef67c226d3c5f026c95b5a1e/package.dhall+        sha256:2c7ac35494f16b1f39afcf3467b2f3b0ab579edb0c711cddd2c93f1cbed358bd++let serviceName = "ipfs"++let apiPort = k8s.IntOrString.Int 5001++let gatewayPort = k8s.IntOrString.Int 8080++let toRule =+      λ ( args+        : { host : Text+          , path : Text+          , serviceName : Text+          , servicePort : k8s.IntOrString+          }+        ) →+        k8s.IngressRule::{+        , host = Some args.host+        , http = Some k8s.HTTPIngressRuleValue::{+          , paths =+            [ k8s.HTTPIngressPath::{+              , path = Some args.path+              , backend = k8s.IngressBackend::args.{ serviceName, servicePort }+              }+            ]+          }+        }++in  [ k8s.Resource.Ingress+        k8s.Ingress::{+        , metadata = k8s.ObjectMeta::{+          , labels = toMap labels+          , name = "${name}-api"+          }+        , spec = Some k8s.IngressSpec::{+          , rules =+            [ toRule+                { host = "localhost"+                , path = "/"+                , serviceName+                , servicePort = gatewayPort+                }+            , toRule+                { host = "localhost"+                , path = "/"+                , serviceName+                , servicePort = apiPort+                }+            ]+          }+        }+    , k8s.Resource.Service+        k8s.Service::{+        , metadata = k8s.ObjectMeta::{+          , name = serviceName+          , labels = toMap labels+          }+        , spec = Some k8s.ServiceSpec::{+          , ports =+            [ k8s.ServicePort::{+              , port = 5001+              , targetPort = Some apiPort+              , name = Some "api"+              }+            , k8s.ServicePort::{+              , port = 8080+              , targetPort = Some gatewayPort+              , name = Some "api"+              }+            ]+          , selector = toMap matchLabels+          }+        }+    , k8s.Resource.StatefulSet+        k8s.StatefulSet::{+        , metadata = k8s.ObjectMeta::{ name, labels = toMap labels }+        , spec = Some k8s.StatefulSetSpec::{+          , serviceName+          , selector = k8s.LabelSelector::{ matchLabels = toMap matchLabels }+          , template = k8s.PodTemplateSpec::{+            , metadata = k8s.ObjectMeta::{ name, labels = toMap labels }+            , spec = Some k8s.PodSpec::{+              , securityContext = Some k8s.PodSecurityContext::{+                , runAsUser = Some 1000+                , runAsGroup = Some 1000+                , fsGroup = Some 1000+                }+              , containers =+                [ k8s.Container::{+                  , name+                  , image = Some "ipfs/go-ipfs:v0.4.22"+                  , livenessProbe = k8s.Probe::{+                    , httpGet = Some k8s.HTTPGetAction::{+                      , path = Some "/debug/metrics/prometheus"+                      , port = k8s.IntOrString.String "api"+                      }+                    , initialDelaySeconds = Some 15+                    , periodSeconds = Some 3+                    }+                  , readinessProbe = k8s.Probe::{+                    , httpGet = Some k8s.HTTPGetAction::{+                      , path = Some "/debug/metrics/prometheus"+                      , port = k8s.IntOrString.String "api"+                      }+                    , initialDelaySeconds = Some 15+                    , periodSeconds = Some 3+                    }+                  , ports =+                    [ k8s.ContainerPort::{+                      , containerPort = 5001+                      , name = Some "api"+                      }+                    , k8s.ContainerPort::{+                      , containerPort = 8080+                      , name = Some "gateway"+                      }+                    ]+                  , volumeMounts =+                    [ k8s.VolumeMount::{+                      , name = "ipfs-storage"+                      , mountPath = "/data/ipfs"+                      }+                    ]+                  }+                ]+              }+            }+          }+        }+    ]
+ tests/format/issue1301A.dhall view
@@ -0,0 +1,5 @@+let attribute+    : Text → Text → { mapKey : Text, mapValue : Text }+    = λ(key : Text) → λ(value : Text) → { mapKey = key, mapValue = value }++in  attribute
+ tests/format/issue1301B.dhall view
@@ -0,0 +1,5 @@+let attribute+    : Text → Text → { mapKey : Text, mapValue : Text }+    = λ(key : Text) → λ(value : Text) → { mapKey = key, mapValue = value }++in  attribute
+ tests/format/issue1400-1A.dhall view
@@ -0,0 +1,14 @@+{ conversation =+    [ { author = "robert", content = xs }+    , { author = "robert", content = xs }+    , { author =+          "bob"+      , content =+          [ text+              ''+              any line going past the 80 characters boundary     (e.g. this one is 82)+              ''+          ]+      }+    ]+}
+ tests/format/issue1400-1B.dhall view
@@ -0,0 +1,13 @@+{ conversation =+  [ { author = "robert", content = xs }+  , { author = "robert", content = xs }+  , { author = "bob"+    , content =+      [ text+          ''+          any line going past the 80 characters boundary     (e.g. this one is 82)+          ''+      ]+    }+  ]+}
+ tests/format/issue1400-2A.dhall view
@@ -0,0 +1,14 @@+let Tagged+    : Type → Type+    =   λ ( a+          : Type+          )+      → { field :+            Text+        , nesting :+              ./Nesting sha256:6284802edd41d5d725aa1ec7687e614e21ad1be7e14dd10996bfa9625105c335+            ? ./Nesting+        , contents : a+        }++in  Tagged
+ tests/format/issue1400-2B.dhall view
@@ -0,0 +1,12 @@+let Tagged+    : Type → Type+    = λ(a : Type) →+        { field : Text+        , nesting :+              ./Nesting+                sha256:6284802edd41d5d725aa1ec7687e614e21ad1be7e14dd10996bfa9625105c335+            ? ./Nesting+        , contents : a+        }++in  Tagged
+ tests/format/issue1413A.dhall view
@@ -0,0 +1,6 @@+let foo =++    {- test -}+      "hello"++in  foo
+ tests/format/issue1413B.dhall view
@@ -0,0 +1,6 @@+let foo =++    {- test -}+      "hello"++in  foo
+ tests/format/issue1545-1A.dhall view
@@ -0,0 +1,1 @@+"\n\tx"
+ tests/format/issue1545-1B.dhall view
@@ -0,0 +1,3 @@+''++${"\t"}x''
+ tests/format/issue1545-2A.dhall view
@@ -0,0 +1,1 @@+"\n x"
+ tests/format/issue1545-2B.dhall view
@@ -0,0 +1,3 @@+''++${" "}x''
+ tests/format/issue1687A.dhall view
@@ -0,0 +1,7 @@+let {- foo++    bar -}+    x =+      1++in  x
+ tests/format/issue1687B.dhall view
@@ -0,0 +1,7 @@+let {- foo++    bar -}+    x =+      1++in  x
+ tests/format/issue1805KeywordRecordFieldShouldBeQuotedA.dhall view
@@ -0,0 +1,1 @@+{ `if` = True }
+ tests/format/issue1805KeywordRecordFieldShouldBeQuotedB.dhall view
@@ -0,0 +1,1 @@+{ `if` = True }
+ tests/format/issue1805SomeQuotedInLetButNotInRecordA.dhall view
@@ -0,0 +1,1 @@+let `Some` = 3 in { `if` = True, Some = 333 }
+ tests/format/issue1805SomeQuotedInLetButNotInRecordB.dhall view
@@ -0,0 +1,1 @@+let `Some` = 3 in { `if` = True, Some = 333 }
+ tests/format/issue183A.dhall view
@@ -0,0 +1,11 @@+    let foo = 1++in    λ(bar : Integer)+    →     let exposePort =+                  λ(portSpec : { ext : Integer, int : Integer })+                → Integer/show portSpec.ext ++ ":" ++ Integer/show portSpec.int+      +      in  let exposeSamePort =+                λ(port : Integer) → exposePort { ext = port, int = port }+      +      in  { blah = bar }
+ tests/format/issue183B.dhall view
@@ -0,0 +1,11 @@+let foo = 1++in  λ(bar : Integer) →+      let exposePort =+            λ(portSpec : { ext : Integer, int : Integer }) →+              Integer/show portSpec.ext ++ ":" ++ Integer/show portSpec.int++      in  let exposeSamePort =+                λ(port : Integer) → exposePort { ext = port, int = port }++          in  { blah = bar }
+ tests/format/issue2047A.dhall view
@@ -0,0 +1,4 @@+let x = ({ foo = 1 } ∧ { bar = 2 })+  with bar = 3 +  with foo = 4 +in x
+ tests/format/issue2047B.dhall view
@@ -0,0 +1,1 @@+let x = ({ foo = 1 } ∧ { bar = 2 }) with bar = 3 with foo = 4 in x
+ tests/format/issue2078A.dhall view
@@ -0,0 +1,1 @@+"'\${x}'\n"
+ tests/format/issue2078B.dhall view
@@ -0,0 +1,3 @@+''+${"'"}''${x}'+''
+ tests/format/issue2601A.dhall view
@@ -0,0 +1,11 @@+let T = < Some | Type >++let t+    : T+    = T.`Some`++let x+    : T+    = T.Type++in  True
+ tests/format/issue2601B.dhall view
@@ -0,0 +1,11 @@+let T = < Some | Type >++let t+    : T+    = T.`Some`++let x+    : T+    = T.Type++in  True
tests/format/largeExponentB.dhall view
@@ -1,1 +1,1 @@-[ 1.0, 1.0e100, 1.0e-100 ]+[ 1.0, 1e100, 1e-100 ]
+ tests/format/largeRecordA.dhall view
@@ -0,0 +1,142 @@+-- This file was tested using console NetHack version 3.6.1+--+-- To exercise all options documented in https://nethackwiki.com/wiki/Options+-- see `./unvalidated.dhall`+let types = ./../types.dhall++let defaults = ./../defaults.dhall++in    defaults.Config+    ⫽ { AUTOCOMPLETE =+          [ { enable = True, value = "zap" }+          , { enable = False, value = "annotate" }+          ]+      , acoustics = Some True+      , align = Some { enable = True, value = types.Alignment.chaotic }+      , autodescribe = Some False+      , autodig = Some False+      , AUTOPICKUP_EXCEPTION =+          [ { pickup = False, name = "chest" }+          , { pickup = True, name = "dagger" }+          ]+      , BIND =+          [ { keybinding = "!", command = "loot" }+          , { keybinding = "^v", command = "untrap" }+          , { keybinding = "M-x", command = "terrain" }+          ]+      , catname = Some "Mirri"+      , checkpoint = Some True+      , checkspace = Some True+      , clicklook = Some False+      , cmdassist = Some True+      , confirm = Some True+      , dark_room = Some False+      , disclose =+          Some+          (   defaults.Disclose+            ⫽ { inventory = Some { prompt = True, default = True }+              , attributes = Some { prompt = True, default = False }+              , monsters_killed = Some { prompt = False, default = True }+              , monsters_genocided = Some { prompt = False, default = False }+              , conduct = Some { prompt = False, default = False }+              , dungeon_overview = Some { prompt = False, default = False }+              }+          )+      , dogname = Some "Cujo"+      , extmenu = Some False+      , fixinv = Some True+      , force_invmenu = Some False+      , fruit = Some "slime mold"+      , gender = Some types.Gender.female+      , goldX = Some False+      , help = Some True+      , hilite_pet = Some False+      , hilite_pile = Some False+      , hilite_status =+            defaults.HiliteStatus+          ⫽ { gold =+                [ { color = types.Color.yellow+                  , trigger = Some types.Numeric.always+                  , attributes = None types.Attributes+                  }+                ]+            }+      , hitpointbar = Some True+      , horsename = Some "Erhir"+      , ignintr = Some False+      , implicit_uncursed = Some True+      , legacy = Some True+      , lit_corridor = Some False+      , lootabc = Some False+      , mail = Some True+      , mention_walls = Some False+      , menucolors =+          [ { regex = "blessed"+            , color = Some types.Color.cyan+            , attributes = defaults.Attributes ⫽ { bold = Some True }+            }+          ]+      , menustyle = Some types.MenuStyle.traditional+      , menu_deselect_all = Some "-"+      , menu_deselect_page = Some "\\"+      , menu_first_page = Some "^"+      , menu_headings = Some types.MenuHeadings.bold+      , menu_invert_all = Some "@"+      , menu_invert_page = Some "~"+      , menu_last_page = Some "|"+      , menu_next_page = Some ">"+      , menu_objsyms = Some False+      , menu_previous_page = Some "<"+      , menu_search = Some ":"+      , menu_select_all = Some "."+      , menu_tab_sep = Some False+      , msg_window = Some types.MsgWindow.single+      , MSGTYPE = [ types.MsgType.hide "You swap places with .*" ]+      , name = Some "Kaeru"+      , news = Some True+      , nudist = Some False+      , null = Some False+      , number_pad = Some types.NumberPad.Letters+      , packorder = Some "\")[%?+!=/(*`0_"+      , paranoid_confirmation =+          defaults.ParanoidConfirmation ⫽ { pray = Some True }+      , pettype = Some types.PetType.cat+      , pickup_burden = Some types.PickupBurden.stressed+      , pickup_thrown = Some True+      , pickup_types = Some "?!/"+      , pile_limit = Some (types.PileLimit.limit 5)+      , playmode = Some types.PlayMode.normal+      , pushweapon = Some False+      , race = Some { enable = True, value = types.Race.elf }+      , rest_on_space = Some False+      , role = Some { enable = True, value = types.Role.wizard }+      , roguesymset = Some types.SymSet.RogueEpyx+      , runmode = Some types.RunMode.walk+      , safe_pet = Some True+      , sanity_check = Some False+      , scores = { own = Some True, around = Some 2, top = Some 10 }+      , showexp = Some False+      , showrace = Some False+      , showscore = Some False+      , silent = Some True+      , sortloot = Some types.SortLoot.none+      , sortpack = Some True+      , sparkle = Some True+      , standout = Some False+      , status_updates = Some True+      , statushilites = Some 10+      , suppress_alert = Some "3.3.1"+      , symset = Some types.SymSet.DECgraphics+      , time = Some False+      , timed_delay = Some True+      , tombstone = Some True+      , toptenwin = Some False+      , travel = Some True+      , verbose = Some True+      , whatis_coord = Some types.WhatisCoord.none+      , whatis_filter = Some types.WhatisFilter.no_filtering+      , whatis_menu = Some False+      , whatis_moveskip = Some False+      , windowtype = Some "tty"+      , wizkit = Some "wizkit.txt"+      }
+ tests/format/largeRecordB.dhall view
@@ -0,0 +1,141 @@+-- This file was tested using console NetHack version 3.6.1+--+-- To exercise all options documented in https://nethackwiki.com/wiki/Options+-- see `./unvalidated.dhall`+let types = ./../types.dhall++let defaults = ./../defaults.dhall++in    defaults.Config+    ⫽ { AUTOCOMPLETE =+        [ { enable = True, value = "zap" }+        , { enable = False, value = "annotate" }+        ]+      , acoustics = Some True+      , align = Some { enable = True, value = types.Alignment.chaotic }+      , autodescribe = Some False+      , autodig = Some False+      , AUTOPICKUP_EXCEPTION =+        [ { pickup = False, name = "chest" }+        , { pickup = True, name = "dagger" }+        ]+      , BIND =+        [ { keybinding = "!", command = "loot" }+        , { keybinding = "^v", command = "untrap" }+        , { keybinding = "M-x", command = "terrain" }+        ]+      , catname = Some "Mirri"+      , checkpoint = Some True+      , checkspace = Some True+      , clicklook = Some False+      , cmdassist = Some True+      , confirm = Some True+      , dark_room = Some False+      , disclose = Some+          (   defaults.Disclose+            ⫽ { inventory = Some { prompt = True, default = True }+              , attributes = Some { prompt = True, default = False }+              , monsters_killed = Some { prompt = False, default = True }+              , monsters_genocided = Some { prompt = False, default = False }+              , conduct = Some { prompt = False, default = False }+              , dungeon_overview = Some { prompt = False, default = False }+              }+          )+      , dogname = Some "Cujo"+      , extmenu = Some False+      , fixinv = Some True+      , force_invmenu = Some False+      , fruit = Some "slime mold"+      , gender = Some types.Gender.female+      , goldX = Some False+      , help = Some True+      , hilite_pet = Some False+      , hilite_pile = Some False+      , hilite_status =+            defaults.HiliteStatus+          ⫽ { gold =+              [ { color = types.Color.yellow+                , trigger = Some types.Numeric.always+                , attributes = None types.Attributes+                }+              ]+            }+      , hitpointbar = Some True+      , horsename = Some "Erhir"+      , ignintr = Some False+      , implicit_uncursed = Some True+      , legacy = Some True+      , lit_corridor = Some False+      , lootabc = Some False+      , mail = Some True+      , mention_walls = Some False+      , menucolors =+        [ { regex = "blessed"+          , color = Some types.Color.cyan+          , attributes = defaults.Attributes ⫽ { bold = Some True }+          }+        ]+      , menustyle = Some types.MenuStyle.traditional+      , menu_deselect_all = Some "-"+      , menu_deselect_page = Some "\\"+      , menu_first_page = Some "^"+      , menu_headings = Some types.MenuHeadings.bold+      , menu_invert_all = Some "@"+      , menu_invert_page = Some "~"+      , menu_last_page = Some "|"+      , menu_next_page = Some ">"+      , menu_objsyms = Some False+      , menu_previous_page = Some "<"+      , menu_search = Some ":"+      , menu_select_all = Some "."+      , menu_tab_sep = Some False+      , msg_window = Some types.MsgWindow.single+      , MSGTYPE = [ types.MsgType.hide "You swap places with .*" ]+      , name = Some "Kaeru"+      , news = Some True+      , nudist = Some False+      , null = Some False+      , number_pad = Some types.NumberPad.Letters+      , packorder = Some "\")[%?+!=/(*`0_"+      , paranoid_confirmation =+          defaults.ParanoidConfirmation ⫽ { pray = Some True }+      , pettype = Some types.PetType.cat+      , pickup_burden = Some types.PickupBurden.stressed+      , pickup_thrown = Some True+      , pickup_types = Some "?!/"+      , pile_limit = Some (types.PileLimit.limit 5)+      , playmode = Some types.PlayMode.normal+      , pushweapon = Some False+      , race = Some { enable = True, value = types.Race.elf }+      , rest_on_space = Some False+      , role = Some { enable = True, value = types.Role.wizard }+      , roguesymset = Some types.SymSet.RogueEpyx+      , runmode = Some types.RunMode.walk+      , safe_pet = Some True+      , sanity_check = Some False+      , scores = { own = Some True, around = Some 2, top = Some 10 }+      , showexp = Some False+      , showrace = Some False+      , showscore = Some False+      , silent = Some True+      , sortloot = Some types.SortLoot.none+      , sortpack = Some True+      , sparkle = Some True+      , standout = Some False+      , status_updates = Some True+      , statushilites = Some 10+      , suppress_alert = Some "3.3.1"+      , symset = Some types.SymSet.DECgraphics+      , time = Some False+      , timed_delay = Some True+      , tombstone = Some True+      , toptenwin = Some False+      , travel = Some True+      , verbose = Some True+      , whatis_coord = Some types.WhatisCoord.none+      , whatis_filter = Some types.WhatisFilter.no_filtering+      , whatis_menu = Some False+      , whatis_moveskip = Some False+      , windowtype = Some "tty"+      , wizkit = Some "wizkit.txt"+      }
+ tests/format/letA.dhall view
@@ -0,0 +1,1 @@+let x = "Lorem ipsum" let y = "Lorem ipsum" in let z = "Lorem ipsum" in x ++ y ++ z
+ tests/format/letAnnotatedShortA.dhall view
@@ -0,0 +1,1 @@+let empty : ∀(a : Type) → List a = λ(a : Type) → [] : List a in empty
+ tests/format/letAnnotatedShortB.dhall view
@@ -0,0 +1,5 @@+let empty+    : ∀(a : Type) → List a+    = λ(a : Type) → [] : List a++in  empty
+ tests/format/letB.dhall view
@@ -0,0 +1,5 @@+let x = "Lorem ipsum"++let y = "Lorem ipsum"++in  let z = "Lorem ipsum" in x ++ y ++ z
+ tests/format/letCommentsA.dhall view
@@ -0,0 +1,7 @@+let {- Example documentation for a let binding+       that spans more than one line+    -}+    x {- we can interject things here -} = -- Make sure one-line comments work+        1++in  x
+ tests/format/letCommentsB.dhall view
@@ -0,0 +1,8 @@+let {- Example documentation for a let binding+       that spans more than one line+    -}+    x {- we can interject things here -} =+    -- Make sure one-line comments work+      1++in  x
+ tests/format/letLineCommentsAfterVariableA.dhall view
@@ -0,0 +1,10 @@+let x -- xxxxxxxxxx xxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxx+    : Natural+    = 0++let y -- yyyyyyyyyy yyyyyyyyyyyyyyyyy yyyyyyyyyyyyyyyyy+      -- yyyyyyyyyyyyyy yyyyyyyyyyyyyyyyyyyyyyy+    : Natural+    = 1++in x + y
+ tests/format/letLineCommentsAfterVariableB.dhall view
@@ -0,0 +1,12 @@+let x+    -- xxxxxxxxxx xxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxx+    : Natural+    = 0++let y+    -- yyyyyyyyyy yyyyyyyyyyyyyyyyy yyyyyyyyyyyyyyyyy+    -- yyyyyyyyyyyyyy yyyyyyyyyyyyyyyyyyyyyyy+    : Natural+    = 1++in  x + y
+ tests/format/letLongCommentsA.dhall view
@@ -0,0 +1,3 @@+let x {- foo                                        -} : {- bar                                           -} Bool {- baz                           -} = {- bla                      -} True++in  x
+ tests/format/letLongCommentsB.dhall view
@@ -0,0 +1,5 @@+let x+    {- foo                                        -} : {- bar                                           -} Bool+    = {- bla                      -} True++in  x
+ tests/format/letNewlineCommentsA.dhall view
@@ -0,0 +1,7 @@+let x = 1+in+let {- aaaaaaaaaaaaaaaaaaa+    -} y : {- bbbbbbbbbbbbbbbbbbbbb+    -} Natural {- cccccccccccccc+    -} = {- ddddddddddddddddd -} 2+    in x
+ tests/format/letNewlineCommentsB.dhall view
@@ -0,0 +1,9 @@+let x = 1++in  let {- aaaaaaaaaaaaaaaaaaa+        -} y+        : {- bbbbbbbbbbbbbbbbbbbbb+          -} Natural+        = {- ddddddddddddddddd -} 2++    in  x
+ tests/format/letShortCommentsA.dhall view
@@ -0,0 +1,3 @@+let x = True+let {- 0 -} y {- 1 -} : {- 2 -} Bool = {- 3-} False+in x
+ tests/format/letShortCommentsB.dhall view
@@ -0,0 +1,7 @@+let x = True++let {- 0 -} y+    {- 1 -} : {- 2 -} Bool+    = {- 3-} False++in  x
+ tests/format/multilineArgumentA.dhall view
@@ -0,0 +1,1 @@+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff xxxxxxxxxxxxxxxx "\n"
+ tests/format/multilineArgumentB.dhall view
@@ -0,0 +1,3 @@+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff+  xxxxxxxxxxxxxxxx+  "\n"
tests/format/multilineB.dhall view
+ tests/format/multilineTrailingSingleQuoteA.dhall view
@@ -0,0 +1,1 @@+"\n'"
+ tests/format/multilineTrailingSingleQuoteB.dhall view
@@ -0,0 +1,3 @@+''++${"'"}''
+ tests/format/multilineTrailingWhitespaceA.dhall view
@@ -0,0 +1,1 @@+{ x = "  \n\nfoo  \n" }
+ tests/format/multilineTrailingWhitespaceB.dhall view
@@ -0,0 +1,7 @@+{ x =+    ''+      ++    foo  +    ''+}
+ tests/format/negativeTimeZoneA.dhall view
@@ -0,0 +1,1 @@+04:00:00-04:00
+ tests/format/negativeTimeZoneB.dhall view
@@ -0,0 +1,1 @@+04:00:00-04:00
+ tests/format/nestedAnnotationA.dhall view
@@ -0,0 +1,1 @@+([] : a) : b
+ tests/format/nestedAnnotationB.dhall view
@@ -0,0 +1,1 @@+([] : a) : b
+ tests/format/numericLiteralsA.dhall view
@@ -0,0 +1,1 @@+{ example0 = 0x42, example1 = +0x42, example2 = 1.2e20, example3 = -0b0111 }
+ tests/format/numericLiteralsB.dhall view
@@ -0,0 +1,1 @@+{ example0 = 0x42, example1 = +0x42, example2 = 1.2e20, example3 = -0b0111 }
tests/format/parentB.dhall view
+ 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/projectionOrderB.dhall view
+ tests/format/punA.dhall view
@@ -0,0 +1,1 @@+{ x = x, y = 1, z = z }
+ tests/format/punB.dhall view
@@ -0,0 +1,1 @@+{ x, y = 1, z }
+ tests/format/punCommentsA.dhall view
@@ -0,0 +1,7 @@+{ {- A -}+  x+  {- B -}+, y =+    {- C -}+    y+}
+ tests/format/punCommentsB.dhall view
@@ -0,0 +1,7 @@+{ {- A -}+  x+  {- B -}+, y =+    {- C -}+    y+}
+ tests/format/recordCompletionA.dhall view
@@ -0,0 +1,26 @@+{ field0 =+T::{+, a = 1+, b = 1+, c = 1+, d = 1+, e = 1+, f = 1+, g = 1+, h = 1+, i = 1+, j = 1+, k = 1+, l = 1+, m = 1+, n = 1+, o = 1+, p = 1+, q = 1+, r = 1+, s = 1+, t = 1+}+, field1 = T::{ a = 1 }+, field2 = T::{ a = a }+}
+ tests/format/recordCompletionB.dhall view
@@ -0,0 +1,25 @@+{ field0 = T::{+  , a = 1+  , b = 1+  , c = 1+  , d = 1+  , e = 1+  , f = 1+  , g = 1+  , h = 1+  , i = 1+  , j = 1+  , k = 1+  , l = 1+  , m = 1+  , n = 1+  , o = 1+  , p = 1+  , q = 1+  , r = 1+  , s = 1+  , t = 1+  }+, field1 = T::{ a = 1 }+, field2 = T::{ a }+}
+ tests/format/recordLitComments0A.dhall view
@@ -0,0 +1,6 @@+{ {- A -}+  x+  {- B -}+  = {- C -}+    T+}
+ tests/format/recordLitComments0B.dhall view
@@ -0,0 +1,6 @@+{ {- A -}+  x+  {- B -}+  = {- C -}+    T+}
+ tests/format/recordLitComments1A.dhall view
@@ -0,0 +1,4 @@+{+--| a comment for y+y = 42+}
+ tests/format/recordLitComments1B.dhall view
@@ -0,0 +1,3 @@+{ --| a comment for y+  y = 42+}
+ tests/format/recordLitMultilineBlockCommentsA.dhall view
@@ -0,0 +1,9 @@+{ {- A+  A -}+  x+  {- B+  B -}+  = {- C+    C -}+    y+}
+ tests/format/recordLitMultilineBlockCommentsB.dhall view
@@ -0,0 +1,9 @@+{ {- A+  A -}+  x+  {- B+  B -}+  = {- C+    C -}+    y+}
+ tests/format/recordTypeCommentsA.dhall view
@@ -0,0 +1,6 @@+{ {- A -}+  a+  {- B -}+  : {- C -}+    A+}
+ tests/format/recordTypeCommentsB.dhall view
@@ -0,0 +1,6 @@+{ {- A -}+  a+  {- B -}+  : {- C -}+    A+}
tests/format/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/significantLeadingSpacesA.dhall view
@@ -0,0 +1,1 @@+"  x\n\n  y\n "
+ tests/format/significantLeadingSpacesB.dhall view
@@ -0,0 +1,5 @@+''+${" "} x++${" "} y+${" "}''
+ tests/format/stringWithNullA.dhall view
@@ -0,0 +1,1 @@+"\u0000 \$ \\ \n ☺"
+ tests/format/stringWithNullB.dhall view
@@ -0,0 +1,3 @@+''+${"\u0000"} $ \ + ☺''
+ tests/format/textLitNewlinesOnlyA.dhall view
@@ -0,0 +1,1 @@+"\n\n"
+ tests/format/textLitNewlinesOnlyB.dhall view
@@ -0,0 +1,1 @@+"\n\n"
+ tests/format/timePrecisionA.dhall view
@@ -0,0 +1,3 @@+-- This test ensures that we don't strip leading zeros from the fractional+-- component of seconds when pretty-printing them+00:00:00.01
+ tests/format/timePrecisionB.dhall view
@@ -0,0 +1,3 @@+-- This test ensures that we don't strip leading zeros from the fractional+-- component of seconds when pretty-printing them+00:00:00.01
tests/format/unicodeA.dhall view
@@ -1,15 +1,15 @@   λ(isActive : Bool) →   { barLeftEnd =-        [ "┨" ] : Optional Text+        Some "┨"     , barRightEnd =-        [ "┠" ] : Optional Text+        Some "┠"     , separator =-        [ "┃" ] : Optional Text+        Some "┃"     , alignment =-          < ToTheLeft = {=} | ToTheRight : {} | Centered : {} >+          < ToTheLeft | ToTheRight | Centered >.ToTheLeft         : ./Alignment.dhall     , barWidth =-        [] : Optional Natural+        None Natural     , barSegments =         [ "index", "command", "path", "title" ]     }
tests/format/unicodeB.dhall view
@@ -1,16 +1,10 @@-  λ(isActive : Bool)-→   { barLeftEnd =-        [ "┨" ] : Optional Text-    , barRightEnd =-        [ "┠" ] : Optional Text-    , separator =-        [ "┃" ] : Optional Text+λ(isActive : Bool) →+    { barLeftEnd = Some "┨"+    , barRightEnd = Some "┠"+    , separator = Some "┃"     , alignment =-          < ToTheLeft = {=} | ToTheRight : {} | Centered : {} >-        : ./Alignment.dhall-    , barWidth =-        [] : Optional Natural-    , barSegments =-        [ "index", "command", "path", "title" ]+        < ToTheLeft | ToTheRight | Centered >.ToTheLeft : ./Alignment.dhall+    , barWidth = None Natural+    , barSegments = [ "index", "command", "path", "title" ]     }   : ./Bar.dhall
+ tests/format/urlsA.dhall view
@@ -0,0 +1,7 @@+let unreserved = http://x/y%7ez++let uppercasehex = http://x/y%3bz++let reserved = http://x/y:z++in "done"
+ tests/format/urlsB.dhall view
@@ -0,0 +1,7 @@+let unreserved = http://x/y~z++let uppercasehex = http://x/y%3Bz++let reserved = http://x/y:z++in  "done"
+ tests/format/usingToMapA.dhall view
@@ -0,0 +1,1 @@+https://httpbin.org/headers using (toMap { TOKEN = "AAAA" }) as Text
+ tests/format/usingToMapB.dhall view
@@ -0,0 +1,1 @@+https://httpbin.org/headers using (toMap { TOKEN = "AAAA" }) as Text
+ tests/format/withA.dhall view
@@ -0,0 +1,5 @@+r with a = Some { b = 1, c = 1, d = 1, e = 1, f = 1, g = 1, h = 1, i = 1, j = 1, k = 1, l = 1 }+  with b = T::{ b = 1, c = 1, d = 1, e = 1, f = 1, g = 1, h = 1, i = 1, j = 1, k = 1, l = 1 }+  with c = [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]+  with d = 1+  with e = 111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
+ tests/format/withB.dhall view
@@ -0,0 +1,58 @@+r+  with a = Some+    { b = 1+    , c = 1+    , d = 1+    , e = 1+    , f = 1+    , g = 1+    , h = 1+    , i = 1+    , j = 1+    , k = 1+    , l = 1+    }+  with b = T::{+    , b = 1+    , c = 1+    , d = 1+    , e = 1+    , f = 1+    , g = 1+    , h = 1+    , i = 1+    , j = 1+    , k = 1+    , l = 1+    }+  with c =+    [ 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    , 1+    ]+  with d = 1+  with e =+      111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
+ tests/format/withPrecedenceA.dhall view
@@ -0,0 +1,5 @@+let Foo =+        Bar+        with default = (Bar.default ⫽ { bar = 0 })++in  Foo
+ tests/format/withPrecedenceB.dhall view
@@ -0,0 +1,1 @@+let Foo = Bar with default = Bar.default ⫽ { bar = 0 } in Foo
+ tests/format/withQuestionA.dhall view
@@ -0,0 +1,1 @@+λ(x : Optional Natural) → x with ? = 2
+ tests/format/withQuestionB.dhall view
@@ -0,0 +1,1 @@+λ(x : Optional Natural) → x with ? = 2
+ tests/freeze/cached/True.dhall view
@@ -0,0 +1,1 @@+True
+ tests/freeze/cached/cachedA.dhall view
@@ -0,0 +1,2 @@+  ./True.dhall sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70+? ./True.dhall
+ tests/freeze/cached/cachedB.dhall view
@@ -0,0 +1,3 @@+  missing+    sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70+? ./True.dhall
+ tests/freeze/cached/idempotentA.dhall view
@@ -0,0 +1,5 @@+-- The purpose of this test is to verify that `dhall freeze --cached` is+-- idempotent and doesn't attempt to resolve the `missing` import+  missing+    sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70+? ./True.dhall
+ tests/freeze/cached/idempotentB.dhall view
@@ -0,0 +1,3 @@+  missing+    sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70+? ./True.dhall
+ tests/freeze/cached/incorrectHashA.dhall view
@@ -0,0 +1,1 @@+./True.dhall sha256:0000000000000000000000000000000000000000000000000000000000000000
+ tests/freeze/cached/incorrectHashB.dhall view
@@ -0,0 +1,3 @@+  missing+    sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70+? ./True.dhall
+ tests/freeze/cached/protectedA.dhall view
@@ -0,0 +1,1 @@+./True.dhall sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ tests/freeze/cached/protectedB.dhall view
@@ -0,0 +1,3 @@+  missing+    sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70+? ./True.dhall
+ tests/freeze/cached/unprotectedA.dhall view
@@ -0,0 +1,1 @@+./True.dhall
+ tests/freeze/cached/unprotectedB.dhall view
@@ -0,0 +1,3 @@+  missing+    sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70+? ./True.dhall
+ tests/freeze/secure/True.dhall view
@@ -0,0 +1,1 @@+True
+ tests/freeze/secure/cachedA.dhall view
@@ -0,0 +1,2 @@+  ./True.dhall sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70+? ./True.dhall
+ tests/freeze/secure/cachedB.dhall view
@@ -0,0 +1,2 @@+./True.dhall+  sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ tests/freeze/secure/incorrectHashA.dhall view
@@ -0,0 +1,1 @@+./True.dhall sha256:0000000000000000000000000000000000000000000000000000000000000000
+ tests/freeze/secure/incorrectHashB.dhall view
@@ -0,0 +1,2 @@+./True.dhall+  sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ tests/freeze/secure/protectedA.dhall view
@@ -0,0 +1,1 @@+./True.dhall sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ tests/freeze/secure/protectedB.dhall view
@@ -0,0 +1,2 @@+./True.dhall+  sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ tests/freeze/secure/unprotectedA.dhall view
@@ -0,0 +1,1 @@+./True.dhall
+ tests/freeze/secure/unprotectedB.dhall view
@@ -0,0 +1,2 @@+./True.dhall+  sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
+ tests/lint/success/PreludeExtensionA.dhall view
@@ -0,0 +1,1 @@+https://prelude.dhall-lang.org/List/map
+ tests/lint/success/PreludeExtensionB.dhall view
@@ -0,0 +1,1 @@+https://prelude.dhall-lang.org/List/map.dhall
+ tests/lint/success/assertA.dhall view
@@ -0,0 +1,14 @@+let simpleAssert = assert : 1 + 1 ≡ 2++let assertIn1Lam = λ(n : Natural) → assert : Natural/subtract 0 n ≡ n++let assertIn2Lams =+        λ(m : Natural)+      → λ(n : Natural)+      → assert : Natural/subtract m m ≡ Natural/subtract n n++let assertInLetInLam = λ(m : Natural) → let n = m + 0 in assert : m ≡ n++let unusedNonAssert = "Foo"++in  {=}
+ tests/lint/success/assertB.dhall view
@@ -0,0 +1,12 @@+let simpleAssert = assert : 1 + 1 ≡ 2++let assertIn1Lam = λ(n : Natural) → assert : Natural/subtract 0 n ≡ n++let assertIn2Lams =+      λ(m : Natural) →+      λ(n : Natural) →+        assert : Natural/subtract m m ≡ Natural/subtract n n++let assertInLetInLam = λ(m : Natural) → let n = m + 0 in assert : m ≡ n++in  {=}
+ tests/lint/success/fixAssertA.dhall view
@@ -0,0 +1,5 @@+let example0 = 1 ≡ 1++let example1 = let x = 1 in x ≡ 1++in 1
+ tests/lint/success/fixAssertB.dhall view
@@ -0,0 +1,1 @@+let example0 = assert : 1 ≡ 1 let example1 = let x = 1 in assert : x ≡ 1 in 1
+ tests/lint/success/issue1586A.dhall view
@@ -0,0 +1,1 @@+let {- 1 -} x {- 2 -} : {- 3 -} Natural = {- 4 -} 1 {- 5 -} in x
+ tests/lint/success/issue1586B.dhall view
@@ -0,0 +1,5 @@+let {- 1 -} x+    {- 2 -} : {- 3 -} Natural+    = {- 4 -} 1++in  x
tests/lint/success/multiletA.dhall view
@@ -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,35 +1,35 @@ -- example0.dhall- let Person     : Type-    =   ∀(Person : Type)-      → ∀(MakePerson : { children : List Person, name : Text } → Person)-      → Person+    = ∀(Person : Type) →+      ∀(MakePerson : { children : List Person, name : Text } → Person) →+        Person  let example     : Person-    =   λ(Person : Type)-      → λ(MakePerson : { children : List Person, name : Text } → Person)-      → MakePerson-        { children =+    = λ(Person : Type) →+      λ(MakePerson : { children : List Person, name : Text } → Person) →+        MakePerson+          { children =             [ MakePerson { children = [] : List Person, name = "Mary" }             , MakePerson { children = [] : List Person, name = "Jane" }             ]-        , name =-            "John"-        }+          , name = "John"+          }  let everybody     : Person → List Text-    = let concat = http://prelude.dhall-lang.org/List/concat-      -      in    λ(x : Person)-          → x-            (List Text)-            (   λ(p : { children : List (List Text), name : Text })-              → [ p.name ] # concat Text p.children-            )+    = let concat = http://prelude.dhall-lang.org/List/concat.dhall -let result : List Text = everybody example+      in  λ(x : Person) →+            x+              (List Text)+              ( λ(p : { children : List (List Text), name : Text }) →+                  [ p.name ] # concat Text p.children+              )++let result+    : List Text+    = everybody example  in  result
tests/lint/success/regression0A.dhall view
@@ -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/recursive/expr0.dhall view
@@ -0,0 +1,17 @@+  λ(Expr : Type)+→ let ExprF =+        < LitF : Natural+        | AddF : { _1 : Expr, _2 : Expr }+        | MulF : { _1 : Expr, _2 : Expr }+        >++  in    λ(Fix : ExprF → Expr)+      → let Lit = λ(x : Natural) → Fix (ExprF.LitF x)++        let Add =+              λ(x : Expr) → λ(y : Expr) → Fix (ExprF.AddF { _1 = x, _2 = y })++        let Mul =+              λ(x : Expr) → λ(y : Expr) → Fix (ExprF.MulF { _1 = x, _2 = y })++        in  Add (Mul (Lit 3) (Lit 7)) (Add (Lit 1) (Lit 2))
+ tests/recursive/expr1.dhall view
@@ -0,0 +1,15 @@+  λ(a : Type)+→ let ExprF =+        < LitF : Natural+        | AddF : { _1 : a, _2 : a }+        | MulF : { _1 : a, _2 : a }+        >++  in    λ(a : ExprF → a)+      → let Lit = λ(x : Natural) → a (ExprF.LitF x)++        let Add = λ(x : a@1) → λ(y : a@1) → a (ExprF.AddF { _1 = x, _2 = y })++        let Mul = λ(x : a@1) → λ(y : a@1) → a (ExprF.MulF { _1 = x, _2 = y })++        in  Add (Mul (Lit 3) (Lit 7)) (Add (Lit 1) (Lit 2))
tests/regression/issue151a.dhall view
@@ -1,1 +1,1 @@-let foo : (\(x : A) -> x x) (\(x : A) -> x x) = 1 in foo+\(A : Type) -> let foo : (\(x : A) -> x x) (\(x : A) -> x x) = 1 in foo
tests/regression/issue151b.dhall view
@@ -1,1 +1,1 @@-\(omega : ((\(x : A) -> x x) (\(x : A) -> x x))) -> omega 1+\(A : Type) -> \(omega : ((\(x : A) -> x x) (\(x : A) -> x x))) -> omega 1
+ tests/regression/issue1584.dhall view
@@ -0,0 +1,19 @@+[ let ifX = 1 in ifX+, let thenX = 1 in thenX+, let elseX = 1 in elseX+, let letX = 1 in letX+, let inX = 1 in inX+, let usingX = 1 in usingX+{- Fixing this case appears to be difficult for the current parser+   implementation+-}+-- , let missingX = 1 in missingX+, let asX = 1 in asX+, let InfinityX = 1 in InfinityX+, let NaNX = 1 in NaNX+, let mergeX = 1 in mergeX+, let SomeX = 1 in SomeX+, let toMapX = 1 in toMapX+, let assertX = 1 in assertX+, let forallX = 1 in forallX+]
+ tests/regression/issue1646.dhall view
@@ -0,0 +1,1 @@+let f = \(d : Double) -> \(i : Integer) -> {=} in f 3.1 -1
+ tests/regression/issue1732.dhall view
@@ -0,0 +1,1 @@+let x = 0 in { x , a = 0 }
+ tests/regression/issue1884.dhall view
@@ -0,0 +1,4 @@+let Make = \(T: Type) -> { Type = { a: T },  default = {=} }++in+(Make Natural) with default = { a = 2 }
+ tests/regression/issue2088.dhall view
@@ -0,0 +1,1 @@+[ { x = 1 }.{ x }, { x = 1 } ]
tests/regression/issue216a.dhall view
@@ -1,5 +1,5 @@ let GitHubProject : Type = { owner : Text, repo : Text } in let gitHubProject = \( github : GitHubProject ) ->      let gitHubRoot = "https://github.com/${github.owner}/${github.repo}"-	 in { bugReports = "${gitHubRoot}/issues"  }+     in  { bugReports = "${gitHubRoot}/issues"  } in gitHubProject
tests/regression/issue216b.dhall view
@@ -1,2 +1,2 @@-  λ(github : { owner : Text, repo : Text })-→ { bugReports = "https://github.com/${github.owner}/${github.repo}/issues" }+λ(github : { owner : Text, repo : Text }) →+  { bugReports = "https://github.com/${github.owner}/${github.repo}/issues" }
+ tests/schemas/multipleA.dhall view
@@ -0,0 +1,1 @@+{=}
+ tests/schemas/multipleB.dhall view
@@ -0,0 +1,1 @@+let schemas = ./tests/schemas/multipleSchema.dhall in schemas.B::{=}
+ tests/schemas/multipleSchema.dhall view
@@ -0,0 +1,3 @@+{ A = { Type = {}, default = {=} }+, B = { Type = {}, default = {=} }+}
+ tests/schemas/personA.dhall view
@@ -0,0 +1,4 @@+{ addr = { city = None Text, country = "Switzerland" }+, alive = True+, name = "Alice"+}
+ tests/schemas/personB.dhall view
@@ -0,0 +1,6 @@+let schemas = ./tests/schemas/personSchema.dhall++in  schemas.Person::{+    , addr = schemas.Address::{ country = "Switzerland" }+    , name = "Alice"+    }
+ tests/schemas/personSchema.dhall view
@@ -0,0 +1,11 @@+let Address =+      { Type = { country : Text, city : Optional Text }+      , default.city = None Text+      }++let Person =+      { Type = { name : Text, addr : Address.Type, alive : Bool }+      , default.alive = True+      }++in  { Person, Address }
+ tests/tags/all.tags view
@@ -0,0 +1,61 @@++./tests/tags/let.dhall,66+let.dhall1,1+/let.dhall1,1+let foo foo1,5+let bar bar3,22++./tests/tags/nonunicode.dhall,63+nonunicode.dhall1,1+/nonunicode.dhall1,1+let foo foo2,12++./tests/tags/record.dhall,335+record.dhall1,1+/record.dhall1,1+let Config Config6,81+      { home home8,161+      , privateKey privateKey9,181+      , publicKey publicKey10,207+      , name name11,232+      , name : { firstName firstName11,241+               , secondName secondName12,275+let makeUser makeUser16,323+let configs configs30,804++./tests/tags/recordlit.dhall,223+recordlit.dhall1,1+/recordlit.dhall1,1+{ home home8,143+, privateKey privateKey9,171+, publicKey publicKey10,215+, name name11,263+, name = { firstName firstName11,272+         , secondName secondName12,302++./tests/tags/simple.dhall,254+simple.dhall1,1+/simple.dhall1,1+let generate generate6,100+let makeUser makeUser17,409+let buildUser buildUser26,680+let Config Config32,880+      { home home33,897+      , privateKey privateKey34,917+      , publicKey publicKey35,943++./tests/tags/unicode.dhall,57+unicode.dhall1,1+/unicode.dhall1,1+let foo foo2,15++./tests/tags/union.dhall,394+union.dhall1,1+/union.dhall1,1+let Element Element1,5+let Element = < Left Left1,17+let Element = < Left : Natural | Right Right1,34+let Element = < Left : Natural | Right : Bool | Middle Middle1,49+let Element = < Left : Natural | Right : Bool | Middle : < Top Top1,60+let Element = < Left : Natural | Right : Bool | Middle : < Top : Text | Bottom Bottom1,73+let foo foo3,95
+ tests/tags/let.dhall view
@@ -0,0 +1,4 @@+let foo = "foo"++let bar = foo+in bar
+ tests/tags/let.tags view
@@ -0,0 +1,6 @@++./tests/tags/let.dhall,66+let.dhall1,1+/let.dhall1,1+let foo foo1,5+let bar bar3,22
+ tests/tags/nonunicode.dhall view
@@ -0,0 +1,3 @@+-- abc+let foo = "bar"+in foo
+ tests/tags/nonunicode.tags view
@@ -0,0 +1,5 @@++./tests/tags/nonunicode.dhall,63+nonunicode.dhall1,1+/nonunicode.dhall1,1+let foo foo2,12
+ tests/tags/record.dhall view
@@ -0,0 +1,35 @@+{- You can optionally add types++   `x : T` means that `x` has type `T`+-}++let Config : Type =+      {- What happens if you add another field here? -}+      { home : Text+      , privateKey : Text+      , publicKey : Text+      , name : { firstName : Text+               , secondName : Text+               }+      }++let makeUser : Text -> Config = \(user : Text) ->+      let home       : Text   = "/home/${user}"+      let privateKey : Text   = "${home}/.ssh/id_ed25519"+      let publicKey  : Text   = "${privateKey}.pub"+      let config     : Config =+            { home       = home+            , privateKey = privateKey+            , publicKey  = publicKey+            , name = { firstName = user+                     , secondName = ""+                     }+            }+      in  config++let configs : List Config =+      [ makeUser "bill"+      , makeUser "jane"+      ]++in  configs
+ tests/tags/record.tags view
@@ -0,0 +1,13 @@++./tests/tags/record.dhall,335+record.dhall1,1+/record.dhall1,1+let Config Config6,81+      { home home8,161+      , privateKey privateKey9,181+      , publicKey publicKey10,207+      , name name11,232+      , name : { firstName firstName11,241+               , secondName secondName12,275+let makeUser makeUser16,323+let configs configs30,804
+ tests/tags/recordlit.dhall view
@@ -0,0 +1,14 @@+{- This is an example Dhall configuration file++   Can you spot the mistake?++   Fix the typo, then move onto the "Definitions" example+-}++{ home       = "/home/bill"+, privateKey = "/home/bill/.ssh/id_ed25519"+, publicKey  = "/home/blil/.ssh/id_ed25519.pub"+, name = { firstName = "Bill"+         , secondName = "Bar"+         }+}
+ tests/tags/recordlit.tags view
@@ -0,0 +1,10 @@++./tests/tags/recordlit.dhall,223+recordlit.dhall1,1+/recordlit.dhall1,1+{ home home8,143+, privateKey privateKey9,171+, publicKey publicKey10,215+, name name11,263+, name = { firstName firstName11,272+         , secondName secondName12,302
+ tests/tags/simple.dhall view
@@ -0,0 +1,39 @@+{- Need to generate a lot of users?++   Use the `generate` function from the Dhall Prelude+-}++let generate = https://prelude.dhall-lang.org/List/generate++{- You can import Dhall expressions from URLs that support+   CORS++   The command-line tools also let you import from files,+   environment variables, and URLs without CORS support.++   Browse https://prelude.dhall-lang.org for more utilities+-}++let makeUser = \(user : Text) ->+      let home       = "/home/${user}"+      let privateKey = "${home}/.ssh/id_ed25519"+      let publicKey  = "${privateKey}.pub"+      in  { home = home+          , privateKey = privateKey+          , publicKey = publicKey+          }++let buildUser = \(index : Natural) ->+      {- `Natural/show` is a "built-in", meaning that+         you can use `Natural/show` without an import+      -}+      makeUser "build${Natural/show index}"++let Config =+      { home : Text+      , privateKey : Text+      , publicKey : Text+      }++in  {- Try generating 20 users instead of 10 -}+    generate 10 Config buildUser
+ tests/tags/simple.tags view
@@ -0,0 +1,11 @@++./tests/tags/simple.dhall,254+simple.dhall1,1+/simple.dhall1,1+let generate generate6,100+let makeUser makeUser17,409+let buildUser buildUser26,680+let Config Config32,880+      { home home33,897+      , privateKey privateKey34,917+      , publicKey publicKey35,943
+ tests/tags/unicode.dhall view
@@ -0,0 +1,3 @@+-- αβξ+let foo = "bar"+in foo
+ tests/tags/unicode.tags view
@@ -0,0 +1,5 @@++./tests/tags/unicode.dhall,57+unicode.dhall1,1+/unicode.dhall1,1+let foo foo2,15
+ tests/tags/union.dhall view
@@ -0,0 +1,4 @@+let Element = < Left : Natural | Right : Bool | Middle : < Top : Text | Bottom : Bool> >++let foo = Element.Left 6+in foo
+ tests/tags/union.tags view
@@ -0,0 +1,11 @@++./tests/tags/union.dhall,394+union.dhall1,1+/union.dhall1,1+let Element Element1,5+let Element = < Left Left1,17+let Element = < Left : Natural | Right Right1,34+let Element = < Left : Natural | Right : Bool | Middle Middle1,49+let Element = < Left : Natural | Right : Bool | Middle : < Top Top1,60+let Element = < Left : Natural | Right : Bool | Middle : < Top : Text | Bottom Bottom1,73+let foo foo3,95
+ tests/th/Department.dhall view
@@ -0,0 +1,1 @@+< Sales | Engineering | Marketing >
+ tests/th/Employee.dhall view
@@ -0,0 +1,1 @@+{ name : Text, department : ./Department.dhall }
+ tests/th/HigherKindSingle.dhall view
@@ -0,0 +1,1 @@+\(a : Type -> Type) -> \(a : Type) -> { foo : a, bar : a@1 a, bam : Text }
+ tests/th/HigherKindUnion.dhall view
@@ -0,0 +1,1 @@+\(a : Type) -> \(b : Type) -> < Foo : a | Bar : b >
+ tests/th/Time.dhall view
@@ -0,0 +1,1 @@+{ txTime : Time, txDate : Date, txTimeZone : TimeZone }
+ tests/th/example.dhall view
@@ -0,0 +1,1 @@+< A : { x : Bool, y : List Text } | B : Optional (List Natural) | C >
+ tests/th/issue2066.dhall view
@@ -0,0 +1,7 @@+let Bar = { baz : Integer }++let Foo = { foo : Integer, bar : Bar }++let Qux = < Foo : Foo | Bar : Bar >++in  { Foo, Bar, Qux }
+ tests/to-directory-tree/fixpoint-allow-path-separators.dhall view
@@ -0,0 +1,25 @@+let User = (./fixpoint-helper.dhall).User++let Group = (./fixpoint-helper.dhall).Group++let Mode = (./fixpoint-helper.dhall).Mode++let Make = (./fixpoint-helper.dhall).Make++in  \(r : Type) ->+    \(make : Make r) ->+      [ make.file+          { name = "non-existent-1/file"+          , content = ""+          , user = None User+          , group = None Group+          , mode = None Mode+          }+      , make.directory+          { name = "non-existent-2/directory"+          , content = [] : List r+          , user = None User+          , group = None Group+          , mode = None Mode+          }+      ]
+ tests/to-directory-tree/fixpoint-empty.dhall view
@@ -0,0 +1,3 @@+let Make = (./fixpoint-helper.dhall).Make++in  \(r : Type) -> \(make : Make r) -> [] : List r
+ tests/to-directory-tree/fixpoint-helper.dhall view
@@ -0,0 +1,30 @@+let User = < UserId : Natural | UserName : Text >++let Group = < GroupId : Natural | GroupName : Text >++let Access =+      { execute : Optional Bool, read : Optional Bool, write : Optional Bool }++let Mode =+      { user : Optional Access+      , group : Optional Access+      , other : Optional Access+      }++let Entry =+      \(content : Type) ->+        { name : Text+        , content : content+        , user : Optional User+        , group : Optional Group+        , mode : Optional Mode+        }++let Make =+      \(r : Type) ->+        { directory : Entry (List r) -> r+        , binary-file : Entry Bytes -> r+        , file : Entry Text -> r+        }++in  { User, Group, Access, Mode, Entry, Make }
+ tests/to-directory-tree/fixpoint-permissions.dhall view
@@ -0,0 +1,24 @@+let User = (./fixpoint-helper.dhall).User++let Group = (./fixpoint-helper.dhall).Group++let Make = (./fixpoint-helper.dhall).Make++let no-access = { execute = Some False, read = Some False, write = Some False }++let full-access = { execute = Some True, read = Some True, write = Some True }++in  \(r : Type) ->+    \(make : Make r) ->+      [ make.file+          { name = "file"+          , content = ""+          , user = None User+          , group = None Group+          , mode = Some+            { user = Some full-access+            , group = Some no-access+            , other = Some no-access+            }+          }+      ]
+ tests/to-directory-tree/fixpoint-simple.dhall view
@@ -0,0 +1,25 @@+let User = (./fixpoint-helper.dhall).User++let Group = (./fixpoint-helper.dhall).Group++let Mode = (./fixpoint-helper.dhall).Mode++let Make = (./fixpoint-helper.dhall).Make++in  \(r : Type) ->+    \(make : Make r) ->+      [ make.file+          { name = "file"+          , content = ""+          , user = None User+          , group = None Group+          , mode = None Mode+          }+      , make.directory+          { name = "directory"+          , content = [] : List r+          , user = None User+          , group = None Group+          , mode = None Mode+          }+      ]
+ tests/to-directory-tree/fixpoint-usergroup.dhall view
@@ -0,0 +1,25 @@+let User = (./fixpoint-helper.dhall).User++let Group = (./fixpoint-helper.dhall).Group++let Mode = (./fixpoint-helper.dhall).Mode++let Make = (./fixpoint-helper.dhall).Make++in  \(r : Type) ->+    \(make : Make r) ->+      [ make.file+          { name = "ids"+          , content = ""+          , user = Some (User.UserId 0)+          , group = Some (Group.GroupId 0)+          , mode = None Mode+          }+      , make.file+          { name = "names"+          , content = ""+          , user = Some (User.UserName "user")+          , group = Some (Group.GroupName "group")+          , mode = None Mode+          }+      ]
+ tests/to-directory-tree/type.dhall view
@@ -0,0 +1,36 @@+let User = < UserId : Natural | UserName : Text >++let Group = < GroupId : Natural | GroupName : Text >++let Access =+      { execute : Optional Bool, read : Optional Bool, write : Optional Bool }++let Mode =+      { user : Optional Access+      , group : Optional Access+      , other : Optional Access+      }++let Entry =+      \(content : Type) ->+        { name : Text+        , content : content+        , user : Optional User+        , group : Optional Group+        , mode : Optional Mode+        }++in  forall (result : Type) ->+      let DirectoryEntry = Entry (List result)++      let BinaryFileEntry = Entry Bytes++      let TextFileEntry = Entry Text++      let Make =+            { directory : DirectoryEntry -> result+            , binary-file : BinaryFileEntry -> result+            , file : TextFileEntry -> result+            }++      in  forall (make : Make) -> List result
+ tests/tutorial/Union.dhall view
@@ -0,0 +1,1 @@+< Left : Natural | Right : Bool>
+ tests/tutorial/substitution1.dhall view
@@ -0,0 +1,1 @@+Result.Failure +1
+ tests/tutorial/substitution2.dhall view
@@ -0,0 +1,1 @@+./substitution1.dhall
+ tests/tutorial/substitution3.dhall view
@@ -0,0 +1,1 @@+Foo
tests/tutorial/unions0A.dhall view
@@ -1,1 +1,1 @@-./process.dhall < Left = 3 | Right : Bool >+./process.dhall ((./Union.dhall).Left 3)
tests/tutorial/unions1A.dhall view
@@ -1,1 +1,1 @@-./process.dhall < Right = True | Left : Natural >+./process.dhall ((./Union.dhall).Right True)
− tests/tutorial/unions2A.dhall
@@ -1,8 +0,0 @@-    let Empty  = < Empty = {=} | Person : { name : Text, age : Natural } >-in  let Person =-        λ(p : { name : Text, age : Natural }) → < Person = p | Empty : {} >-in  [   Empty-    ,   Person { name = "John", age = 23 }-    ,   Person { name = "Amy" , age = 25 }-    ,   Empty-    ]
− tests/tutorial/unions2B.dhall
@@ -1,5 +0,0 @@-[ < Empty = {=} | Person : { age : Natural, name : Text } >-, < Person = { age = 23, name = "John" } | Empty : {} >-, < Person = { age = 25, name = "Amy" } | Empty : {} >-, < Empty = {=} | Person : { age : Natural, name : Text } >-]