dhall-1.19.1/0000755000000000000000000000000013377175666011102 5ustar0000000000000000dhall-1.19.1/CHANGELOG.md0000644000000000000000000010772513377175666012727 0ustar00000000000000001.19.1 * BUG FIX: Fix serious `dhall lint` bug * `dhall lint` would sometimes remove `let` expressions that were still in use * See: https://github.com/dhall-lang/dhall-haskell/pull/703 * BUG FIX: Fix import caching efficiency bug * Some imports were being wastefully fetched multiple times * See: https://github.com/dhall-lang/dhall-haskell/pull/702 * Feature: Generate dot graph to visualize import graph * Use the `dhall resolve --dot` command * See: https://github.com/dhall-lang/dhall-haskell/pull/698 * See: https://github.com/dhall-lang/dhall-haskell/pull/713 * Improve HTTP error messages * See: https://github.com/dhall-lang/dhall-haskell/pull/710 1.19.0 * Supports version 4.0.0 of the language standard * See: https://github.com/dhall-lang/dhall-lang/releases/tag/v4.0.0 * BREAKING CHANGE TO THE LANGUAGE AND API: Prevent Hurkens' paradox * This fixes a type-checking soundness bug which permitted infinite loops * This is a breaking change because infinite loops are no longer possible * This is also a breaking change because a record of types is now treated as a kind instead of a type * See: https://github.com/dhall-lang/dhall-haskell/pull/680 * BREAKING CHANGE TO THE LANGUAGE AND API: `Double`s are now double-precision floating point numbers * This restricts the range of `Double`s to IEEE 754 double-precision floating point * This also implies that you can no longer convert `Scientific` values to `Dhall` expressions (i.e. no `Inject` instance for `Scientific`) * See: https://github.com/dhall-lang/dhall-haskell/pull/667 * BREAKING CHANGE TO THE API: Preserve field order for record projection * The API uses a new `Dhall.Set.Set` type instead of `Data.Set.Set` * See: https://github.com/dhall-lang/dhall-haskell/pull/670 * BREAKING CHANGE TO THE API: Add support for multi-`let` expressions * This changes the `Let` constructor to now support storing multiple bindings per `let` expression * See: https://github.com/dhall-lang/dhall-haskell/pull/675 * Access constructors as if they were fields of the union type * In other words: `< Left : Bool | Right : Natural >.Left` * See: https://github.com/dhall-lang/dhall-haskell/pull/657 * Support GHC 8.6 * See: https://github.com/dhall-lang/dhall-haskell/pull/669 * Add support for quoted path components * i.e. `/"foo"/bar/"baz qux"` or `https://example.com/foo/"bar?baz"?qux` * See: https://github.com/dhall-lang/dhall-haskell/pull/690 * Fix parsing of `//\\` operator * See: https://github.com/dhall-lang/dhall-haskell/commit/9d0fd42d95ab69fa64da4afd8b60d69aca8e65a6 * Preserve Unicode characters when formatting code * See: https://github.com/dhall-lang/dhall-haskell/pull/679 * Allow identifier names to begin with `Some` * See: https://github.com/dhall-lang/dhall-haskell/pull/658 * Add `subExpressions` `Traversal` * See: https://github.com/dhall-lang/dhall-haskell/pull/660 * Add `normalizeWithM` for monadic normalization * See: https://github.com/dhall-lang/dhall-haskell/pull/371 * Custom normalizers now take precedence over default normalization logic * This allows one to override the implementation of built-in operators * See: https://github.com/dhall-lang/dhall-haskell/pull/684 1.18.0 * Supports version 3.0.0 of the language standard: * See: https://github.com/dhall-lang/dhall-lang/releases/tag/v3.0.0 * BREAKING CHANGE TO THE LANGUAGE AND API: New `Some`/`None` constructors for `Optional` values * Example: `[ Some 1, None Natural ]` * This is a breaking change to the language because `Some` and `None` are now reserved keywords * This is a breaking change to the API because `Some` and `None` are new constructors for the `Expr` type * BREAKING CHANGE TO THE LANGUAGE AND API: Support for kind polymorphism * This adds a new `Sort` constant above `Kind` in the hierarchy * i.e. `Type : Kind : Sort` * This is a breaking change to the language because `Sort` is now a reserved keyword * This is a breaking change to the API because `Sort` is a new constructor for the `Expr` type * BREAKING CHANGE TO THE API: New `Dhall.Map` module * This replaces `InsOrdHashMap` in the API * The primary motivation is to improve performance and to remove the dependency on `insert-ordered-containers` * BREAKING CHANGE TO THE API: Use standard version instead of protocol version * The binary protocol is now versioned alongside the standard * The `ProtocolVersion` type is renamed to `StandardVersion` and the * `--protocol-version` option is renamed to `--standard-version` * See: https://github.com/dhall-lang/dhall-haskell/pull/634 * BUG FIX: Fix import chaining for custom header imports * See: https://github.com/dhall-lang/dhall-haskell/pull/618 * BUG FIX: Fix import chaining for imports protected by semantic integrity checks * See: https://github.com/dhall-lang/dhall-haskell/pull/584 * BUG FIX: Record literals and types produced by `∧`/`⫽`/`⩓` are now sorted * This ensures that β-normalization is idempotent * See: https://github.com/dhall-lang/dhall-haskell/pull/572 * BUG FIX: `dhall freeze` now correctly handles the starting file being located outside the current working directory * See: https://github.com/dhall-lang/dhall-haskell/commit/a22aa79d1957be9ecf166ea066e2a9a5b309e1ae * BUG FIX: Fix parsing of IPv4-mapped IPv6 addresses * See: https://github.com/dhall-lang/dhall-haskell/pull/632 * FEATURE: New `--ascii` flag for ASCII output * See: https://github.com/dhall-lang/dhall-haskell/pull/570 * FEATURE: New `dhall encode` and `dhall decode` subcommands * These allow you to transform Dhall source code to and from its binary representation * See: https://github.com/dhall-lang/dhall-haskell/pull/588 * LARGE parsing performance improvements * Parsing is about 10x-100x faster on most code * See: https://github.com/dhall-lang/dhall-haskell/pull/591 * See: https://github.com/dhall-lang/dhall-haskell/pull/592 * See: https://github.com/dhall-lang/dhall-haskell/pull/597 * See: https://github.com/dhall-lang/dhall-haskell/pull/601 * See: https://github.com/dhall-lang/dhall-haskell/pull/602 * See: https://github.com/dhall-lang/dhall-haskell/pull/604 * See: https://github.com/dhall-lang/dhall-haskell/pull/606 * Type-checking performance improvements: * See: https://github.com/dhall-lang/dhall-haskell/pull/566 * Normalization performance improvements: * See: https://github.com/dhall-lang/dhall-haskell/pull/610 * `dhall freeze` now caches the imports as it freezes them * See: https://github.com/dhall-lang/dhall-haskell/pull/587 * `dhall freeze` now refreezes imports with invalid semantic integrity checks * See: https://github.com/dhall-lang/dhall-haskell/pull/637 * `dhall freeze` now adds a trailing newline * See: https://github.com/dhall-lang/dhall-haskell/pull/629 * Build against `megaparsec-7.0.*` * See: https://github.com/dhall-lang/dhall-haskell/pull/565 * Support GHC 8.6 * See: https://github.com/dhall-lang/dhall-haskell/pull/599 * See: https://github.com/dhall-lang/dhall-haskell/pull/623 * Support GHC all the way back to 7.10.3 * See: https://github.com/dhall-lang/dhall-haskell/pull/595 * See: https://github.com/dhall-lang/dhall-haskell/pull/621 * Improvements to error messages: * See: https://github.com/dhall-lang/dhall-haskell/pull/563 * See: https://github.com/dhall-lang/dhall-haskell/pull/576 * See: https://github.com/dhall-lang/dhall-haskell/pull/583 * See: https://github.com/dhall-lang/dhall-haskell/pull/589 1.17.0 * This release corresponds to version 2.0.0 of the language standard * BREAKING CHANGE TO THE LANGUAGE AND API: Binary serialization support * This is a breaking change to the hash for all semantic integrity checks * The hash used by the semantic integrity check is now based on the binary representation instead of a text representation of the expression * You can pin the new hashes by supplying the `--protocol-version 1.0` option on the command line until you need support for newer language features * This also includes a breaking change to `ImportType` in the API * BREAKING CHANGE TO THE LANGUAGE: Disallow combining records of terms and types * This is mainly for consistency and to improve type errors that would have otherwise happened further downstream * This should not affect the vast majority of code * See: https://github.com/dhall-lang/dhall-haskell/pull/538 * BUG FIX: Semantic integrity checks now work for imported expression using the `constructors` keyword * See: https://github.com/dhall-lang/dhall-haskell/pull/554 * BUG FIX: Fix α-normalization of expressions with bound variables named `_` * See: https://github.com/dhall-lang/dhall-haskell/pull/524 * BUG FIX: Fix `isNormalized` to match `normalize` * See: https://github.com/dhall-lang/dhall-haskell/pull/522 * BUG FIX: `dhall lint` now correctly handles nested `let` expressions * See: https://github.com/dhall-lang/dhall-haskell/pull/555 * FEATURE: Imports protected by a semantic integrity check are now cached * See: https://github.com/dhall-lang/dhall-haskell/pull/533 * The default `dhall` command no longer outputs the type to `stderr` * You can add back the type as a type annotation using the `--annotate` switch * See: https://github.com/dhall-lang/dhall-haskell/pull/544 * New utilities for building `InputTypes` * See: https://github.com/dhall-lang/dhall-haskell/pull/530 * Improve parsing performance for long variable names * See: https://github.com/dhall-lang/dhall-haskell/pull/526 * More succinct type diffs for function types * See: https://github.com/dhall-lang/dhall-haskell/pull/540 * Identifier names can now begin with keywords * i.e. `ifChanged` and `lettuce` are now legal identifiers * See: https://github.com/dhall-lang/dhall-haskell/pull/551 1.16.1 * Fix test failure due to missing test data file 1.16.0 * BREAKING CHANGE: Consolidate `input` family of functions * These now take a record of options * This also `_stack` field of the `Status` type from `[Import]` to `NonEmpty Import` * Permit `$` in quoted variable names * See: https://github.com/dhall-lang/dhall-haskell/pull/510 1.15.1 * Fix infinite loop when formatting expressions containing `?` * See: https://github.com/dhall-lang/dhall-haskell/pull/491 1.15.0 * BREAKING CHANGE TO THE API: Support alternative imports using new `?` operator * This adds a new constructor which affects exhaustive pattern matches * See: https://github.com/dhall-lang/dhall-haskell/pull/473 * BREAKING CHANGE TO THE API: Add `Integer/toDouble` built-in function * This adds a new constructor which affects exhaustive pattern matches * See: https://github.com/dhall-lang/dhall-haskell/pull/434 * BREAKING CHANGE TO THE API: Use strict `Text` instead of lazy `Text` * See: https://github.com/dhall-lang/dhall-haskell/pull/455 * BREAKING CHANGE TO THE API: Remove `Buildable` in favor of `Pretty` * See: https://github.com/dhall-lang/dhall-haskell/pull/459 * BREAKING CHANGE TO THE API: Removed the `Parent` constructor from `FilePrefix` * Instead, use `Here` with a `".."` prefix. * See: https://github.com/dhall-lang/dhall-haskell/pull/407 * BUG FIX: Disallow duplicate fields in records * See: https://github.com/dhall-lang/dhall-haskell/pull/430 * BUG FIX: Fix stripping of leading whitespace in multi-line strings * See: https://github.com/dhall-lang/dhall-haskell/pull/469 * BUG FIX: Fix formatting field access of an import * See: https://github.com/dhall-lang/dhall-haskell/pull/471 * Add `dhall freeze` command * See: https://github.com/dhall-lang/dhall-haskell/pull/486 * Add `dhall diff` command * See: https://github.com/dhall-lang/dhall-haskell/pull/442 * Add `dhall lint` command * See: https://github.com/dhall-lang/dhall-haskell/pull/484 * Change `dhall-repl`/`dhall-hash`/`dhall-format` to `dhall` subcommands * i.e. `dhall repl`/`dhall hash`/`dhall format` * See: https://github.com/dhall-lang/dhall-haskell/pull/435 * See: https://github.com/dhall-lang/dhall-haskell/pull/452 * Add `with-http` cabal flag to disable support for remote imports * See: https://github.com/dhall-lang/dhall-haskell/pull/482 * Added `inputFrom` and `inputFromWith` * These allow naming the file that the expression is coming from for better error messages * See: https://github.com/dhall-lang/dhall-haskell/pull/464 * Performance improvements * See: https://github.com/dhall-lang/dhall-haskell/pull/420 * Tutorial recommends GitHub for Prelude instead of IPFS * See: https://github.com/dhall-lang/dhall-haskell/pull/479 * Pretty-print expressions in type errors * See: https://github.com/dhall-lang/dhall-haskell/pull/429 * Formatting improvements * See: https://github.com/dhall-lang/dhall-haskell/pull/398 * See: https://github.com/dhall-lang/dhall-haskell/pull/458 * Diff improvements * See: https://github.com/dhall-lang/dhall-haskell/pull/455 * See: https://github.com/dhall-lang/dhall-haskell/pull/470 * See: https://github.com/dhall-lang/dhall-haskell/pull/478 1.14.0 * BREAKING CHANGE TO THE LANGUAGE: Switch grammar of `Natural` and `Integer` * `Natural` number literals are now unsigned and `Integer` literals always require a sign * This is a **VERY** disruptive change to most Dhall code in the wild but was unanimously agreed upon here: https://github.com/dhall-lang/dhall-lang/issues/138 * See also: https://github.com/dhall-lang/dhall-haskell/pull/381 * BREAKING CHANGE TO THE LANGUAGE: Drop support for importing directories * Importing `dir/` used to resolve to `dir/@`, which is no longer supported * See: https://github.com/dhall-lang/dhall-haskell/pull/384 * BREAKING CHANGE TO THE LANGUAGE: Change to the grammar for imports * File path components can no longer contain `#` or `?` characters * URL imports must now contain at least one path component * URL path components must match the grammar for file path components * See: https://github.com/dhall-lang/dhall-haskell/pull/390 * BREAKING CHANGE TO THE API: Rename `Path{,Mode,Hashed,Type}` to `Import{,Mode,Hashed,Type}` * In practice this change is not breaking for the most common use cases since this also provides a `Path` type synonym for backwards compatibility * See: https://github.com/dhall-lang/dhall-haskell/pull/376 * BUG FIX: Fix α-equivalence bug when type-checking `merge` * `merge` expressions would sometimes reject valid code due to a type-checking bug * See: https://github.com/dhall-lang/dhall-haskell/pull/394 * Improve import caching * See: https://github.com/dhall-lang/dhall-haskell/pull/388 * See: https://github.com/dhall-lang/dhall-haskell/pull/392 * Increase upper bound on `tasty` * See: https://github.com/dhall-lang/dhall-haskell/pull/382 * Fix lower bound on `insert-ordered-containers` * See: https://github.com/dhall-lang/dhall-haskell/pull/377 1.13.1 * Increase upper bound on `ansi-terminal` and `megaparsec` 1.13.0 * BUG FIX: Fix semantic integrity hashing support * Both parsing and pretty-printing semantic hashes were broken since version 1.11.0 * See: https://github.com/dhall-lang/dhall-haskell/pull/345 * BUG FIX: Allow leading whitespace in interpolated expresssions * See: https://github.com/dhall-lang/dhall-haskell/pull/369 * BUG FIX: Fix `deriving (Interpret)` for sum types * The types of alternatives were not correctly included in the corresponding Dhall type * See: https://github.com/dhall-lang/dhall-haskell/pull/348 * BREAKING CHANGE TO LANGUAGE: Records cannot store both types and terms * Records can also not store type-level functions (like `List`) * Records might be allowed to store type-level functions again in the future * This fixes a potential soundness bug * The primarily practical consequence of this change is that if you are hosting a "package" then you will need to split terms and types from your package into different records for your users to import * This also implies removing the `./Monoid` type-level function from the `./Prelude/package.dhall` record * See: https://github.com/dhall-lang/dhall-haskell/pull/335 * BREAKING CHANGE TO THE API: Replace `trifecta` with `megaparsec` * This change the API to use the `Parser` type from `megaparsec` * This also slightly changes the type of `exprFromText` * If you program using the type classes provided by the `parsers` library then this is not a breaking change as that interface is preserved * See: https://github.com/dhall-lang/dhall-haskell/pull/268 * BREAKING CHANGE TO THE API: New `⩓` operator for merging record types * Example: `{ foo : Text } ⩓ { bar : Bool } = { foo : Text, bar : Bool }` * This is breaking because it adds a new constructor to the `Expr` type * See: https://github.com/dhall-lang/dhall-haskell/pull/342 * BREAKING CHANGE TO THE API: New support for projecting a subset of fields * Example: `{ x = 1, y = 2, z = 3 }.{ x, y } = { x = 1, y = 2 }` * This is breaking because it adds a new constructor to the `Expr` type * See: https://github.com/dhall-lang/dhall-haskell/pull/350 * API+UX feature: New support for pretty-printing diffs of Dhall expressions * Error messages also use this feature to simplify large type mismatches * There is also a new `Dhall.Diff` module * See: https://github.com/dhall-lang/dhall-haskell/pull/336 * Add `version`, `resolve`, `type`, and `normalize` sub-commands to interpreter * See: https://github.com/dhall-lang/dhall-haskell/pull/352 * Support GHC 7.10.3 * See: https://github.com/dhall-lang/dhall-haskell/pull/340 * `:type` command in `dhall-repl` now only displays the type * Before it would also display the original expression * See: https://github.com/dhall-lang/dhall-haskell/pull/344 * Trim dependency tree * See: https://github.com/dhall-lang/dhall-haskell/pull/351 * See: https://github.com/dhall-lang/dhall-haskell/pull/268 * See: https://github.com/dhall-lang/dhall-haskell/pull/355 1.12.0 * Additional changes to support GHC 8.4 * See: https://github.com/dhall-lang/dhall-haskell/pull/331 * BREAKING CHANGE TO API: Replace dependency on `text-format` with `formatting` * This replace the `Data.Text.Buildable.Buildable` instances with `Formatting.Buildable.Buildable` instances, which is why this is a breaking change * `text-format` is no longer maintained and blocking GHC 8.4 support * See: https://github.com/dhall-lang/dhall-haskell/pull/330 1.11.1 * Support GHC 8.4 * See: https://github.com/dhall-lang/dhall-haskell/pull/321 * Fix α-normalization bug * Note that this is not a type-checking bug. This only affects users who were directly using the `alphaNormalize` function from the Haskell API because `let` expressions were not correctly α-normalized * See: https://github.com/dhall-lang/dhall-haskell/pull/319 * Slight tweak to syntax highlighting * See: https://github.com/dhall-lang/dhall-haskell/pull/324 * Increase upper bound on `ansi-terminal` and `exceptions` * See: https://github.com/dhall-lang/dhall-haskell/pull/322 * See: https://github.com/dhall-lang/dhall-haskell/pull/325 1.11.0 * BREAKING CHANGE TO THE API: Fix `{Natural,Optional,List}/build` semantics to match standard * This is a breaking change because the `OptionalLit` and `ListLit` constructors changed their representations to efficiently support the standard semantics * `ListLit` now stores a `Data.Sequence.Seq` instead of a `Data.Vector.Vector` * `OptionalLit` now stores a `Maybe` instead of a `Data.Vector.Vector` * See: https://github.com/dhall-lang/dhall-haskell/pull/300 * BREAKING CHANGE TO THE COMMAND LINE: `dhall` executable always formats output * Previously you had to opt into formatting using `--pretty` * Now formatting is obligatory and the `--pretty` flag is gone * See: https://github.com/dhall-lang/dhall-haskell/pull/303 * Feature: New `:save` command for `dhall-repl` * Now you can save an expression to a file: `./yourFile = someExpression` * See: https://github.com/dhall-lang/dhall-haskell/pull/309 * Improvement: Add new simplifications to match standard * See: https://github.com/dhall-lang/dhall-haskell/pull/312 * See: https://github.com/dhall-lang/dhall-haskell/pull/316 * Improvement: Fix equivalence check to match standard * Practically this means that more corner cases of the language correctly type-check than before * Improvement: New `--plain` flag to disable syntax highlighting * See: https://github.com/dhall-lang/dhall-haskell/pull/310 * Improvement: Prelude now provides an umbrella `package.dhall` import * This is primarily for convenience * See: https://github.com/dhall-lang/dhall-haskell/pull/298 * Improvement: Context is now normalized * See: https://github.com/dhall-lang/dhall-haskell/pull/302 * Replace `cryptohash` dependency with `cryptonite` * See: https://github.com/dhall-lang/dhall-haskell/commit/5d2012927a062ec8bdf2bbaba77150344f38db77 * Increase upper bound on exceptions * See: https://github.com/dhall-lang/dhall-haskell/pull/306 * Fix type error in tutorial * See: https://github.com/dhall-lang/dhall-haskell/commit/5a9126b2f684d3236fc1e8e20e206cfaf47d97db 1.10.0 * Feature: Records/unions can now have fields/alternatives that are types * i.e. `{ foo = Text, bar = List }` is legal now * See: https://github.com/dhall-lang/dhall-haskell/pull/273 * Feature: New `dhall-repl` for interactively evaluating Dhall expressions * See: https://github.com/dhall-lang/dhall-haskell/pull/266 * Feature: Syntax highlighting * See: https://github.com/dhall-lang/dhall-haskell/pull/260 * Feature: BREAKING CHANGE TO THE API: `dhall-format` preserves field order * This changes the syntax tree to use an `InsOrdHashMap` instead of a `Map` * BREAKING CHANGE TO THE API: Use Haskell's `Scientific` type * This is fixes the interpreter to correct handle really large/small numbers * This also allows marshaling into Haskell's `Scientific` type * See: https://github.com/dhall-lang/dhall-haskell/pull/256 * BREAKING CHANGE TO THE API: Remove `system-filepath`/`system-fileio` dependencies * Now the library uses `Prelude.FilePath` * See: https://github.com/dhall-lang/dhall-haskell/pull/248 * Feature: Labels can now begin with reserved names * i.e. `List/map` is now a legal label * See: https://github.com/dhall-lang/dhall-haskell/pull/255 * Fix: Rendered labels are now correctly escaped if they are numbers * See: https://github.com/dhall-lang/dhall-haskell/pull/252 * Add the instance `Interpret String`. * See: https://github.com/dhall-lang/dhall-haskell/pull/247 * Fix: Custom contexts passed to `typeWith` are now checked * This prevents a custom context from triggering an infinite loop * See: https://github.com/dhall-lang/dhall-haskell/pull/259 1.9.1 * `dhall-format` now emits single-quoted strings for multi-line strings * See: https://github.com/dhall-lang/dhall-haskell/pull/237 * Improved error messages for list elements with the wrong type * See: https://github.com/dhall-lang/dhall-haskell/pull/236 * Change `lens` dependency to `lens-family-core` * See: https://github.com/dhall-lang/dhall-haskell/pull/238 1.9.0 * Feature: BREAKING CHANGE TO LANGUAGE AND API: Add `constructors` keyword * This new keyword generates constructors from a union type * See the updated Haskell tutorial for more details * This means that `constructors` is now a reserved keyword * This adds a new `Constructors` constructor to the `Expr` type * See: https://github.com/dhall-lang/dhall-haskell/pull/199 * Feature: BREAKING CHANGE TO THE API: `dhall-format` preserves interpolation * This changes the `TextLit` constructor to represent an interpolated `Text` literal * See: https://github.com/dhall-lang/dhall-haskell/pull/220 * Feature: You can now define type synonyms using `let` * See: https://github.com/dhall-lang/dhall-haskell/pull/202 * Feature: Extend valid set of quoted labels * See: https://github.com/dhall-lang/dhall-lang/pull/65 * See: https://github.com/dhall-lang/dhall-lang/pull/77 * Performance: Improve startup time when importing files, but not URLs * See: https://github.com/dhall-lang/dhall-haskell/pull/194 * Security: `localhost`/`127.0.0.1` imports no longer count as local imports * Specifically: they cannot import environment variables or files * See: https://github.com/dhall-lang/dhall-haskell/pull/197 * Security: Fix potential type-checking bug * See: https://github.com/dhall-lang/dhall-haskell/pull/198 * Fix: BREAKING CHANGE TO API: Improve localization of error messages * This required fixing the type of `normalize`/`shift`/`subst` to preserve the first type parameter of `Expr` (i.e. they no longer delete `Note` constructors) * A new `denote` function was added for the explicit purpose of deleting `Note` constructors * See: https://github.com/dhall-lang/dhall-haskell/pull/218 * Expose `MissingEnvironmentVariable` exception type * See: https://github.com/dhall-lang/dhall-haskell/pull/196 * Add `genericAuto` * See: https://github.com/dhall-lang/dhall-haskell/pull/195 * Add `inputWith` * See: https://github.com/dhall-lang/dhall-haskell/pull/222 * Add`loadWithContext` * See: https://github.com/dhall-lang/dhall-haskell/pull/215 * Add `pair`/`unit`/`string`/`list` * See: https://github.com/dhall-lang/dhall-haskell/pull/227 1.8.2 * Add `typeWithA` for type-checking custom `Embed`ded values * Fix `dhall{,-*}` executables to ignore ambient locale and use UTF8 * Increase upper bound on `tasty` dependency 1.8.1 * `dhall` executable can now format output using `--pretty` * Improved Unicode suppport on Windows 1.8.0 * BREAKING CHANGE TO LANGUAGE: Add support for import integrity checks * In practice, the likelihood of this breaking code in the wild is astronomically low * This would only break code of the form `sha256:aaa...aaa` (i.e. a variabled named `sha256` with a type annotation for a type with a name 64 characters long drawn from the first 6 characters of the alphabet) * BUG FIX: Fix parsing of single quotes in single-quoted strings * BUG FIX: Fix superfluous parentheses introduced by `dhall-format` * New `dhall-hash` executable * This goes hand-in-hand with the added support for integrity checks since the executable lets you compute the current hash of an import 1.7.0 * BREAKING CHANGE TO LANGUAGE: Update parser to match standardized grammar * Trailing commas and bars no longer supported for union and record literals * Paths no longer permit commas * URL grammar is now RFC-compliant * Environment variables can now be quoted to support full range of POSIX-compliant names * Text literals support full set of JSON escape sequences (such as `\u2192`) * BREAKING CHANGE TO LANGUAGE: Single quoted strings strip leading newlines * BUG FIX: Fixed type-checking infinite loops due to non-type-checked variables in context * BUG FIX: Fixed type-checking bug due to missing context when type-checking certain expressions * BUG FIX: Fixed type-checking bug due to off-by-one errors in name shadowing logic * New `dhall-format` executable to automatically format code * Performance optimizations to `Natural/fold` and `List/fold` * Improved parsing performance (over 3x faster) * Union literals can now specify the set value anywhere in the literal * i.e. `< A : Integer | B = False | C : Text >` * New `Inject` instance for `()` * Several tutorial fixes and improvements 1.6.0 * BREAKING CHANGE TO THE API: Drop support for GHC 7.* * BREAKING CHANGE TO THE API: Add support for customizing Dhall import * This is a breaking change because this changes the type of `loadWith` * BREAKING CHANGE TO THE API: Add field to `UnboundVariable` error containing * BUG FIX: Fix parsing single quotes in string literals the name of the unbound variable * Add `List/concatMap` to the Prelude * You can now derive `Inject` and `Interpret` for types with unlabeled fields * Add new instances for `Interpret`: * `[]` * `(,)` * Add new instance for `Inject` * `[]`, `Data.Set.Set`, `Data.Sequence.Seq` * `(,)` * `Int`, `Word8`, `Word16`, `Word32`, `Word64` * Add `Eq` instance for `Src` 1.5.1 * Increase upper bound on `vector` and `optparse-generic` 1.5.0 * BREAKING CHANGE: Add list concatenation operator: `(#)` * This is a breaking change because it adds a new constructor to the `Expr` type which breaks exhaustive pattern matches * BREAKING CHANGE: Add `Interpret` support for lazy `Text` * This is a breaking change because it renames `text` to `strictText` * Add `Interpret` instance for decoding (a limited subset of) Dhall functions * Dhall no longer requires Template Haskell to compile * This helps with cross-compilation * Add `rawInput` utility for decoding a Haskell value from the `Expr` type * Add `loadWith`/`normalizeWith` utilities for normalizing/importing modules with a custom context * Export `Type` constructor 1.4.2 * Fix missing `Prelude` files in package archive uploaded to Hackage 1.4.1 * Fix missing `tests/Tutorial.hs` module in package archive uploaded to Hackage 1.4.0 * BREAKING CHANGE TO THE LANGUAGE AND API: You can now supply custom headers for URL imports with the new `using` keyword * This is a breaking change to the language because this adds a new reserved `using` keyword * This is a breaking change to the API because this adds a new field to the `URL` constructor to store optional custom headers * BUG FIX: `:` is no longer a disallowed path character * This was breaking URL imports with a port * BUG FIX: If you import a home-anchored path (i.e. `~/foo`) and that imports a relative path (like `./bar`), then the canonical path of the relative import should be home-anchored (i.e. `~/bar`). However, there was a bug that made lose the home anchor (i.e. `./foo/bar`), which this release fixes likely fail due to no longer being home-anchored (i.e. `./foob * Add support for string interpolation * `merge` no longer requires a type annotation if you are merging at least one alternative * Expanded Prelude * `./Prelude/Optional/all` * `./Prelude/Optional/any` * `./Prelude/Optional/filter` * `./Prelude/Optional/length` * `./Prelude/Optional/null` * `./Prelude/Text/concatMap` * `./Prelude/Text/concatMapSep` * `./Prelude/Text/concatSep` * Rearrange detailed error messages to put summary information at the bottom of the message 1.3.0 * BREAKING CHANGE TO THE API: Add support for new primitives, specifically: * `(//)` - Right-biased and shallow record merge * `Optional/build` (now a built-in in order to support build/fold fusion) * `Natural/show` * `Integer/show` * `Double/show` * `Natural/toInteger` * These all add new constructors to the `Expr` type, which would break exhaustive pattern matches * BREAKING CHANGE TO THE LANGUAGE: Imported paths and URLs no longer support the characters: "()[]{}<>:" * This reduces the number of cases where you have to add a space after imports * Note that this does not exclude the `:` in the URL scheme (i.e. `http://`) * Increase connection timeout for imports * Variable names now allow the `-` character for all but the first character * You can now escape identifiers with backticks * This lets you name identifiers so that they don't conflict with reserved key words * This is most useful when converting Dhall to other file formats (like JSON) where you might need to emit a field that conflicts with one of Dhall's reserved keywords * New `--version` flag for the `dhall` executable 1.2.0 * BREAKING CHANGE: Add support for customizing derived `Interpret` instances * This is a breaking change to the Dhall library API since this changes the signature of the `Interpret` class by replacing the `auto` method with a more general `autoWith` method. This `autoWith` now takes an `InterpretOptions` argument that lets you customize derived field and constuctor names * In practice user programs that use the common path will be unaffected by this change * This is not a breaking change to the Dhall language * BREAKING CHANGE: Type annotations now bind more tightly than lambda abstraction * This is a breaking change to the Dhall language. An expression like this: ``` λ(x : A) → y : B ``` ... used to parenthesized implicitly as: ``` (λ(x : A) → y) : T ``` ... but is now parenthesized implicitly as: ``` λ(x : A) → (y : T) ``` This is now consistent with Haskell's precedence and also consistent with the precedence of `List` and `Optional` type annotations * This change affects programs with an expression like this: ``` -- Assuming that `y : B` λ(x : A) → y : A → B ``` The above program would type-check before this change but not type-check after this change. You would you need to fix the above program by either changing the type signature to annotate just the type of `y` like this: ``` λ(x : A) → y : B ``` ... or by adding explicit parentheses like this: ``` (λ(x : A) → y) : A → B ``` * This is not a breaking change to the Dhall library API * BREAKING CHANGE: Add support for importing a path's contents as raw `Text` by adding `as Text` after the import * This is a breaking change to the Dhall language * This is technically a breaking change, but is extremely unlikely to affect you program. This only changes the behavior of old programs that had an expression of the form: ``` /some/imported/function as Text ``` ... where `/some/imported/function` is an imported function being applied to two arguments, the first of which is a bound variable named `as` and the second of which is the type `Text` * This is not a breaking change to the Dhall library API * BREAKING CHANGE: Add support for importing environment variables using `env:VAR` syntax * This is a breaking change to the Dhall library API since it adds a new `Path` constructor * This also technically a breaking change to the Dhall language but extremely unlikely to affect your program. This only changes the behavior of old programs that had an expression of the form: ``` env:VAR ``` ... where `env` was the name of a bound variable and `:VAR` was a type annotation without spaces around the type annotation operator After this change the program would be interpreted as an import of the contents for the environment variable named `VAR` * BREAKING CHANGE: Support importing paths relative to home directory using `~/some/path` syntax * This is a breaking change to the Dhall library API since it adds a new field to the `File` constructor indicating whether or not the imported path is relative to the home directory * This is not a breaking change to the Dhall language and the new syntax does not override any old syntax * Permit trailing commas and bars in record/union syntax * Improve location information for parsing errors 1.1.0 * BREAKING CHANGE: Non-empty lists no longer require a type annotation * This is a breaking change to the Haskell library, not the Dhall language * This change does not break existing Dhall programs * The `Expr` type was modified in a non-backwards-compatible way * Add new `exprA` parser * Add new `InvalidType` exception if `input` fails on an invalid `Type` * Improve documentation and tutorial 1.0.2 * Add support for Nix-style "double single-quote" multi-line string literals * Add `isNormalized` * Improve documentation and tutorial * Build against wider range of `http-client` versions 1.0.1 * Initial release 1.0.0 * Accidental premature upload to Hackage. This release was blacklisted dhall-1.19.1/dhall.cabal0000644000000000000000000005324713377175666013165 0ustar0000000000000000Name: dhall Version: 1.19.1 Cabal-Version: >=1.10 Build-Type: Simple Tested-With: GHC == 8.0.1 License: BSD3 License-File: LICENSE Copyright: 2017 Gabriel Gonzalez Author: Gabriel Gonzalez Maintainer: Gabriel439@gmail.com Bug-Reports: https://github.com/dhall-lang/dhall-haskell/issues Synopsis: A configuration language guaranteed to terminate Description: Dhall is an explicitly typed configuration language that is not Turing complete. Despite being Turing incomplete, Dhall is a real programming language with a type-checker and evaluator. . Use this library to parse, type-check, evaluate, and pretty-print the Dhall configuration language. This package also includes an executable which type-checks a Dhall file and reduces the file to a fully evaluated normal form. . Read "Dhall.Tutorial" to learn how to use this library Category: Compiler Extra-Source-Files: benchmark/deep-nested-large-record/*.dhall benchmark/examples/*.dhall CHANGELOG.md Prelude/Monoid Prelude/package.dhall tests/format/*.dhall tests/import/data/fieldOrder/*.dhall tests/import/data/foo/bar/*.dhall tests/import/failure/*.dhall tests/import/success/*.dhall tests/lint/success/*.dhall tests/normalization/success/*.dhall tests/normalization/success/haskell-tutorial/access/*.dhall tests/normalization/success/haskell-tutorial/combineTypes/*.dhall tests/normalization/success/haskell-tutorial/prefer/*.dhall tests/normalization/success/haskell-tutorial/projection/*.dhall tests/normalization/success/prelude/Bool/and/*.dhall tests/normalization/success/prelude/Bool/and/*.dhall tests/normalization/success/prelude/Bool/build/*.dhall tests/normalization/success/prelude/Bool/build/*.dhall tests/normalization/success/prelude/Bool/even/*.dhall tests/normalization/success/prelude/Bool/even/*.dhall tests/normalization/success/prelude/Bool/fold/*.dhall tests/normalization/success/prelude/Bool/fold/*.dhall tests/normalization/success/prelude/Bool/not/*.dhall tests/normalization/success/prelude/Bool/not/*.dhall tests/normalization/success/prelude/Bool/odd/*.dhall tests/normalization/success/prelude/Bool/odd/*.dhall tests/normalization/success/prelude/Bool/or/*.dhall tests/normalization/success/prelude/Bool/or/*.dhall tests/normalization/success/prelude/Bool/show/*.dhall tests/normalization/success/prelude/Bool/show/*.dhall tests/normalization/success/prelude/Double/show/*.dhall tests/normalization/success/prelude/Double/show/*.dhall tests/normalization/success/prelude/Integer/show/*.dhall tests/normalization/success/prelude/Integer/show/*.dhall tests/normalization/success/prelude/Integer/toDouble/*.dhall tests/normalization/success/prelude/Integer/toDouble/*.dhall tests/normalization/success/prelude/List/all/*.dhall tests/normalization/success/prelude/List/all/*.dhall tests/normalization/success/prelude/List/any/*.dhall tests/normalization/success/prelude/List/any/*.dhall tests/normalization/success/prelude/List/build/*.dhall tests/normalization/success/prelude/List/build/*.dhall tests/normalization/success/prelude/List/concat/*.dhall tests/normalization/success/prelude/List/concat/*.dhall tests/normalization/success/prelude/List/concatMap/*.dhall tests/normalization/success/prelude/List/concatMap/*.dhall tests/normalization/success/prelude/List/filter/*.dhall tests/normalization/success/prelude/List/filter/*.dhall tests/normalization/success/prelude/List/fold/*.dhall tests/normalization/success/prelude/List/fold/*.dhall tests/normalization/success/prelude/List/generate/*.dhall tests/normalization/success/prelude/List/generate/*.dhall tests/normalization/success/prelude/List/head/*.dhall tests/normalization/success/prelude/List/head/*.dhall tests/normalization/success/prelude/List/indexed/*.dhall tests/normalization/success/prelude/List/indexed/*.dhall tests/normalization/success/prelude/List/iterate/*.dhall tests/normalization/success/prelude/List/iterate/*.dhall tests/normalization/success/prelude/List/last/*.dhall tests/normalization/success/prelude/List/last/*.dhall tests/normalization/success/prelude/List/length/*.dhall tests/normalization/success/prelude/List/length/*.dhall tests/normalization/success/prelude/List/map/*.dhall tests/normalization/success/prelude/List/map/*.dhall tests/normalization/success/prelude/List/null/*.dhall tests/normalization/success/prelude/List/null/*.dhall tests/normalization/success/prelude/List/replicate/*.dhall tests/normalization/success/prelude/List/replicate/*.dhall tests/normalization/success/prelude/List/reverse/*.dhall tests/normalization/success/prelude/List/reverse/*.dhall tests/normalization/success/prelude/List/shifted/*.dhall tests/normalization/success/prelude/List/shifted/*.dhall tests/normalization/success/prelude/List/unzip/*.dhall tests/normalization/success/prelude/List/unzip/*.dhall tests/normalization/success/prelude/Natural/build/*.dhall tests/normalization/success/prelude/Natural/build/*.dhall tests/normalization/success/prelude/Natural/enumerate/*.dhall tests/normalization/success/prelude/Natural/enumerate/*.dhall tests/normalization/success/prelude/Natural/even/*.dhall tests/normalization/success/prelude/Natural/even/*.dhall tests/normalization/success/prelude/Natural/fold/*.dhall tests/normalization/success/prelude/Natural/fold/*.dhall tests/normalization/success/prelude/Natural/isZero/*.dhall tests/normalization/success/prelude/Natural/isZero/*.dhall tests/normalization/success/prelude/Natural/odd/*.dhall tests/normalization/success/prelude/Natural/odd/*.dhall tests/normalization/success/prelude/Natural/product/*.dhall tests/normalization/success/prelude/Natural/product/*.dhall tests/normalization/success/prelude/Natural/show/*.dhall tests/normalization/success/prelude/Natural/show/*.dhall tests/normalization/success/prelude/Natural/sum/*.dhall tests/normalization/success/prelude/Natural/sum/*.dhall tests/normalization/success/prelude/Natural/toDouble/*.dhall tests/normalization/success/prelude/Natural/toDouble/*.dhall tests/normalization/success/prelude/Natural/toInteger/*.dhall tests/normalization/success/prelude/Natural/toInteger/*.dhall tests/normalization/success/prelude/Optional/all/*.dhall tests/normalization/success/prelude/Optional/all/*.dhall tests/normalization/success/prelude/Optional/any/*.dhall tests/normalization/success/prelude/Optional/any/*.dhall tests/normalization/success/prelude/Optional/build/*.dhall tests/normalization/success/prelude/Optional/build/*.dhall tests/normalization/success/prelude/Optional/concat/*.dhall tests/normalization/success/prelude/Optional/concat/*.dhall tests/normalization/success/prelude/Optional/filter/*.dhall tests/normalization/success/prelude/Optional/filter/*.dhall tests/normalization/success/prelude/Optional/fold/*.dhall tests/normalization/success/prelude/Optional/fold/*.dhall tests/normalization/success/prelude/Optional/head/*.dhall tests/normalization/success/prelude/Optional/head/*.dhall tests/normalization/success/prelude/Optional/last/*.dhall tests/normalization/success/prelude/Optional/last/*.dhall tests/normalization/success/prelude/Optional/length/*.dhall tests/normalization/success/prelude/Optional/length/*.dhall tests/normalization/success/prelude/Optional/map/*.dhall tests/normalization/success/prelude/Optional/map/*.dhall tests/normalization/success/prelude/Optional/null/*.dhall tests/normalization/success/prelude/Optional/null/*.dhall tests/normalization/success/prelude/Optional/toList/*.dhall tests/normalization/success/prelude/Optional/toList/*.dhall tests/normalization/success/prelude/Optional/unzip/*.dhall tests/normalization/success/prelude/Optional/unzip/*.dhall tests/normalization/success/prelude/Text/concat/*.dhall tests/normalization/success/prelude/Text/concat/*.dhall tests/normalization/success/prelude/Text/concatMap/*.dhall tests/normalization/success/prelude/Text/concatMap/*.dhall tests/normalization/success/prelude/Text/concatMapSep/*.dhall tests/normalization/success/prelude/Text/concatMapSep/*.dhall tests/normalization/success/prelude/Text/concatSep/*.dhall tests/normalization/success/prelude/Text/concatSep/*.dhall tests/normalization/success/simple/*.dhall tests/normalization/success/simplifications/*.dhall tests/parser/failure/*.dhall tests/parser/success/*.dhall tests/regression/*.dhall tests/tutorial/*.dhall tests/typecheck/failure/*.dhall tests/typecheck/success/*.dhall tests/typecheck/success/prelude/Bool/and/*.dhall tests/typecheck/success/prelude/Bool/and/*.dhall tests/typecheck/success/prelude/Bool/build/*.dhall tests/typecheck/success/prelude/Bool/build/*.dhall tests/typecheck/success/prelude/Bool/even/*.dhall tests/typecheck/success/prelude/Bool/even/*.dhall tests/typecheck/success/prelude/Bool/fold/*.dhall tests/typecheck/success/prelude/Bool/fold/*.dhall tests/typecheck/success/prelude/Bool/not/*.dhall tests/typecheck/success/prelude/Bool/not/*.dhall tests/typecheck/success/prelude/Bool/odd/*.dhall tests/typecheck/success/prelude/Bool/odd/*.dhall tests/typecheck/success/prelude/Bool/or/*.dhall tests/typecheck/success/prelude/Bool/or/*.dhall tests/typecheck/success/prelude/Bool/show/*.dhall tests/typecheck/success/prelude/Bool/show/*.dhall tests/typecheck/success/prelude/Double/show/*.dhall tests/typecheck/success/prelude/Double/show/*.dhall tests/typecheck/success/prelude/Integer/show/*.dhall tests/typecheck/success/prelude/Integer/show/*.dhall tests/typecheck/success/prelude/Integer/toDouble/*.dhall tests/typecheck/success/prelude/Integer/toDouble/*.dhall tests/typecheck/success/prelude/List/all/*.dhall tests/typecheck/success/prelude/List/all/*.dhall tests/typecheck/success/prelude/List/any/*.dhall tests/typecheck/success/prelude/List/any/*.dhall tests/typecheck/success/prelude/List/build/*.dhall tests/typecheck/success/prelude/List/build/*.dhall tests/typecheck/success/prelude/List/concat/*.dhall tests/typecheck/success/prelude/List/concat/*.dhall tests/typecheck/success/prelude/List/concatMap/*.dhall tests/typecheck/success/prelude/List/concatMap/*.dhall tests/typecheck/success/prelude/List/filter/*.dhall tests/typecheck/success/prelude/List/filter/*.dhall tests/typecheck/success/prelude/List/fold/*.dhall tests/typecheck/success/prelude/List/fold/*.dhall tests/typecheck/success/prelude/List/generate/*.dhall tests/typecheck/success/prelude/List/generate/*.dhall tests/typecheck/success/prelude/List/head/*.dhall tests/typecheck/success/prelude/List/head/*.dhall tests/typecheck/success/prelude/List/indexed/*.dhall tests/typecheck/success/prelude/List/indexed/*.dhall tests/typecheck/success/prelude/List/iterate/*.dhall tests/typecheck/success/prelude/List/iterate/*.dhall tests/typecheck/success/prelude/List/last/*.dhall tests/typecheck/success/prelude/List/last/*.dhall tests/typecheck/success/prelude/List/length/*.dhall tests/typecheck/success/prelude/List/length/*.dhall tests/typecheck/success/prelude/List/map/*.dhall tests/typecheck/success/prelude/List/map/*.dhall tests/typecheck/success/prelude/List/null/*.dhall tests/typecheck/success/prelude/List/null/*.dhall tests/typecheck/success/prelude/List/replicate/*.dhall tests/typecheck/success/prelude/List/replicate/*.dhall tests/typecheck/success/prelude/List/reverse/*.dhall tests/typecheck/success/prelude/List/reverse/*.dhall tests/typecheck/success/prelude/List/shifted/*.dhall tests/typecheck/success/prelude/List/shifted/*.dhall tests/typecheck/success/prelude/List/unzip/*.dhall tests/typecheck/success/prelude/List/unzip/*.dhall tests/typecheck/success/prelude/Monoid/*.dhall tests/typecheck/success/prelude/Natural/build/*.dhall tests/typecheck/success/prelude/Natural/build/*.dhall tests/typecheck/success/prelude/Natural/enumerate/*.dhall tests/typecheck/success/prelude/Natural/enumerate/*.dhall tests/typecheck/success/prelude/Natural/even/*.dhall tests/typecheck/success/prelude/Natural/even/*.dhall tests/typecheck/success/prelude/Natural/fold/*.dhall tests/typecheck/success/prelude/Natural/fold/*.dhall tests/typecheck/success/prelude/Natural/isZero/*.dhall tests/typecheck/success/prelude/Natural/isZero/*.dhall tests/typecheck/success/prelude/Natural/odd/*.dhall tests/typecheck/success/prelude/Natural/odd/*.dhall tests/typecheck/success/prelude/Natural/product/*.dhall tests/typecheck/success/prelude/Natural/product/*.dhall tests/typecheck/success/prelude/Natural/show/*.dhall tests/typecheck/success/prelude/Natural/show/*.dhall tests/typecheck/success/prelude/Natural/sum/*.dhall tests/typecheck/success/prelude/Natural/sum/*.dhall tests/typecheck/success/prelude/Natural/toDouble/*.dhall tests/typecheck/success/prelude/Natural/toDouble/*.dhall tests/typecheck/success/prelude/Natural/toInteger/*.dhall tests/typecheck/success/prelude/Natural/toInteger/*.dhall tests/typecheck/success/prelude/Optional/all/*.dhall tests/typecheck/success/prelude/Optional/all/*.dhall tests/typecheck/success/prelude/Optional/any/*.dhall tests/typecheck/success/prelude/Optional/any/*.dhall tests/typecheck/success/prelude/Optional/build/*.dhall tests/typecheck/success/prelude/Optional/build/*.dhall tests/typecheck/success/prelude/Optional/concat/*.dhall tests/typecheck/success/prelude/Optional/concat/*.dhall tests/typecheck/success/prelude/Optional/filter/*.dhall tests/typecheck/success/prelude/Optional/filter/*.dhall tests/typecheck/success/prelude/Optional/fold/*.dhall tests/typecheck/success/prelude/Optional/fold/*.dhall tests/typecheck/success/prelude/Optional/head/*.dhall tests/typecheck/success/prelude/Optional/head/*.dhall tests/typecheck/success/prelude/Optional/last/*.dhall tests/typecheck/success/prelude/Optional/last/*.dhall tests/typecheck/success/prelude/Optional/length/*.dhall tests/typecheck/success/prelude/Optional/length/*.dhall tests/typecheck/success/prelude/Optional/map/*.dhall tests/typecheck/success/prelude/Optional/map/*.dhall tests/typecheck/success/prelude/Optional/null/*.dhall tests/typecheck/success/prelude/Optional/null/*.dhall tests/typecheck/success/prelude/Optional/toList/*.dhall tests/typecheck/success/prelude/Optional/toList/*.dhall tests/typecheck/success/prelude/Optional/unzip/*.dhall tests/typecheck/success/prelude/Optional/unzip/*.dhall tests/typecheck/success/prelude/Text/concat/*.dhall tests/typecheck/success/prelude/Text/concat/*.dhall tests/typecheck/success/prelude/Text/concatMap/*.dhall tests/typecheck/success/prelude/Text/concatMap/*.dhall tests/typecheck/success/prelude/Text/concatMapSep/*.dhall tests/typecheck/success/prelude/Text/concatMapSep/*.dhall tests/typecheck/success/prelude/Text/concatSep/*.dhall tests/typecheck/success/prelude/Text/concatSep/*.dhall tests/typecheck/success/simple/access/*.dhall tests/typecheck/success/simple/*.dhall Source-Repository head Type: git Location: https://github.com/dhall-lang/dhall-haskell/tree/master/dhall Flag with-http Description: Include support for importing dhall modules from HTTP URLs Default: True Manual: True Library Hs-Source-Dirs: src Build-Depends: base >= 4.8.2.0 && < 5 , ansi-terminal >= 0.6.3.1 && < 0.9 , bytestring < 0.11, case-insensitive < 1.3 , cborg >= 0.2.0.0 && < 0.3 , containers >= 0.5.0.0 && < 0.7 , contravariant < 1.6 , cryptonite >= 0.23 && < 1.0 , Diff >= 0.2 && < 0.4 , directory >= 1.2.2.0 && < 1.4 , dotgen >= 0.4.2 && < 0.5 , 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 >= 7.0.0 && < 7.1 , memory >= 0.14 && < 0.15, mtl >= 2.2.1 && < 2.3 , optparse-applicative >= 0.14.0.0 && < 0.15, parsers >= 0.12.4 && < 0.13, prettyprinter >= 1.2.0.1 && < 1.3 , prettyprinter-ansi-terminal >= 1.1.1 && < 1.2 , repline >= 0.2.0.0 && < 0.3 , 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 , unordered-containers >= 0.1.3.0 && < 0.3 , uri-encode < 1.6 , vector >= 0.11.0.0 && < 0.13 if flag(with-http) Build-Depends: http-types >= 0.7.0 && < 0.13, http-client >= 0.4.30 && < 0.6 , http-client-tls >= 0.2.0 && < 0.4 if !impl(ghc >= 8.0) Build-Depends: semigroups == 0.18.* Build-Depends: transformers == 0.4.2.* Build-Depends: fail == 4.9.* 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.Set, Dhall.Parser, Dhall.Pretty, Dhall.Repl, Dhall.TH, Dhall.Tutorial, Dhall.TypeCheck Other-Modules: Dhall.Pretty.Internal, Dhall.Parser.Expression, Dhall.Parser.Combinators, Dhall.Parser.Token, Dhall.Import.Types, Dhall.Util, Paths_dhall if flag(with-http) Other-Modules: Dhall.Import.HTTP GHC-Options: -Wall Default-Language: Haskell2010 Executable dhall Hs-Source-Dirs: dhall Main-Is: Main.hs Build-Depends: base, dhall GHC-Options: -Wall -rtsopts Default-Language: Haskell2010 Test-Suite tasty Type: exitcode-stdio-1.0 Hs-Source-Dirs: tests Main-Is: Tests.hs GHC-Options: -Wall Other-Modules: Format Import Lint Normalization Parser QuickCheck Regression Tutorial TypeCheck Util Build-Depends: base >= 4 && < 5 , containers , deepseq >= 1.2.0.1 && < 1.5 , dhall , directory , filepath , prettyprinter , QuickCheck >= 2.10 && < 2.13, quickcheck-instances >= 0.3.12 && < 0.4 , serialise , tasty >= 0.11.2 && < 1.2 , tasty-hunit >= 0.9.2 && < 0.11, tasty-quickcheck >= 0.9.2 && < 0.11, text >= 0.11.1.0 && < 1.3 , transformers , vector >= 0.11.0.0 && < 0.13 Default-Language: Haskell2010 Test-Suite doctest 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) Buildable: False Benchmark dhall-parser 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 Default-Language: Haskell2010 ghc-options: -rtsopts Benchmark deep-nested-large-record 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 dhall-1.19.1/LICENSE0000644000000000000000000000270413377175666012112 0ustar0000000000000000Copyright (c) 2018 Gabriel Gonzalez All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. dhall-1.19.1/Setup.hs0000644000000000000000000000005613377175666012537 0ustar0000000000000000import Distribution.Simple main = defaultMain dhall-1.19.1/benchmark/0000755000000000000000000000000013377175666013034 5ustar0000000000000000dhall-1.19.1/benchmark/deep-nested-large-record/0000755000000000000000000000000013377175666017575 5ustar0000000000000000dhall-1.19.1/benchmark/deep-nested-large-record/BigEnum.dhall0000644000000000000000000000666013377175666022141 0ustar0000000000000000< A0 : {} | A1 : {} | A2 : {} | A3 : {} | A4 : {} | A5 : {} | A6 : {} | A7 : {} | A8 : {} | A9 : {} | A10 : {} | A11 : {} | A12 : {} | A13 : {} | A14 : {} | A15 : {} | A16 : {} | A17 : {} | A18 : {} | A19 : {} | A20 : {} | A21 : {} | A22 : {} | A23 : {} | A24 : {} | A25 : {} | A26 : {} | A27 : {} | A28 : {} | A29 : {} | A30 : {} | A31 : {} | A32 : {} | A33 : {} | A34 : {} | A35 : {} | A36 : {} | A37 : {} | A38 : {} | A39 : {} | A40 : {} | A41 : {} | A42 : {} | A43 : {} | A44 : {} | A45 : {} | A46 : {} | A47 : {} | A48 : {} | A49 : {} | A50 : {} | A51 : {} | A52 : {} | A53 : {} | A54 : {} | A55 : {} | A56 : {} | A57 : {} | A58 : {} | A59 : {} | A60 : {} | A61 : {} | A62 : {} | A63 : {} | A64 : {} | A65 : {} | A66 : {} | A67 : {} | A68 : {} | A69 : {} | A70 : {} | A71 : {} | A72 : {} | A73 : {} | A74 : {} | A75 : {} | A76 : {} | A77 : {} | A78 : {} | A79 : {} | A80 : {} | A81 : {} | A82 : {} | A83 : {} | A84 : {} | A85 : {} | A86 : {} | A87 : {} | A88 : {} | A89 : {} | A90 : {} | A91 : {} | A92 : {} | A93 : {} | A94 : {} | A95 : {} | A96 : {} | A97 : {} | A98 : {} | A99 : {} | A100 : {} | A101 : {} | A102 : {} | A103 : {} | A104 : {} | A105 : {} | A106 : {} | A107 : {} | A108 : {} | A109 : {} | A110 : {} | A111 : {} | A112 : {} | A113 : {} | A114 : {} | A115 : {} | A116 : {} | A117 : {} | A118 : {} | A119 : {} | A120 : {} | A121 : {} | A122 : {} | A123 : {} | A124 : {} | A125 : {} | A126 : {} | A127 : {} | A128 : {} | A129 : {} | A130 : {} | A131 : {} | A132 : {} | A133 : {} | A134 : {} | A135 : {} | A136 : {} | A137 : {} | A138 : {} | A139 : {} | A140 : {} | A141 : {} | A142 : {} | A143 : {} | A144 : {} | A145 : {} | A146 : {} | A147 : {} | A148 : {} | A149 : {} | A150 : {} | A151 : {} | A152 : {} | A153 : {} | A154 : {} | A155 : {} | A156 : {} | A157 : {} | A158 : {} | A159 : {} | A160 : {} | A161 : {} | A162 : {} | A163 : {} | A164 : {} | A165 : {} | A166 : {} | A167 : {} | A168 : {} | A169 : {} | A170 : {} | A171 : {} | A172 : {} | A173 : {} | A174 : {} | A175 : {} | A176 : {} | A177 : {} | A178 : {} | A179 : {} | A180 : {} | A181 : {} | A182 : {} | A183 : {} | A184 : {} | A185 : {} | A186 : {} | A187 : {} | A188 : {} | A189 : {} | A190 : {} | A191 : {} | A192 : {} | A193 : {} | A194 : {} | A195 : {} | A196 : {} | A197 : {} | A198 : {} | A199 : {} | A200 : {} | A201 : {} | A202 : {} | A203 : {} | A204 : {} | A205 : {} | A206 : {} | A207 : {} | A208 : {} | A209 : {} | A210 : {} | A211 : {} | A212 : {} | A213 : {} | A214 : {} | A215 : {} | A216 : {} | A217 : {} | A218 : {} | A219 : {} | A220 : {} | A221 : {} | A222 : {} | A223 : {} | A224 : {} | A225 : {} | A226 : {} | A227 : {} | A228 : {} | A229 : {} | A230 : {} | A231 : {} | A232 : {} | A233 : {} | A234 : {} | A235 : {} | A236 : {} | A237 : {} | A238 : {} | A239 : {} | A240 : {} | A241 : {} | A242 : {} | A243 : {} | A244 : {} | A245 : {} | A246 : {} | A247 : {} | A248 : {} | A249 : {} | A250 : {} | A251 : {} | A252 : {} | A253 : {} | A254 : {} | A255 : {} | A256 : {} | A257 : {} | A258 : {} | A259 : {} | A260 : {} | A261 : {} | A262 : {} | A263 : {} | A264 : {} | A265 : {} | A266 : {} | A267 : {} | A268 : {} | A269 : {} | A270 : {} | A271 : {} | A272 : {} | A273 : {} | A274 : {} | A275 : {} | A276 : {} | A277 : {} | A278 : {} | A279 : {} | A280 : {} | A281 : {} | A282 : {} | A283 : {} | A284 : {} | A285 : {} | A286 : {} | A287 : {} | A288 : {} | A289 : {} | A290 : {} | A291 : {} | A292 : {} | A293 : {} | A294 : {} | A295 : {} | A296 : {} | A297 : {} | A298 : {} | A299 : {} | A300 : {} > dhall-1.19.1/benchmark/deep-nested-large-record/LittleEnum.dhall0000644000000000000000000000004313377175666022662 0ustar0000000000000000< Foo : {} | Bar : {} | Baz : {} > dhall-1.19.1/benchmark/deep-nested-large-record/Main.hs0000644000000000000000000000320113377175666021011 0ustar0000000000000000{-# LANGUAGE OverloadedStrings #-} module Main (main) where import Criterion.Main (defaultMain) 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 Dhall.TypeCheck as TypeCheck dhallPreludeImport :: Core.Import dhallPreludeImport = Core.Import { Core.importMode = Core.Code , Core.importHashed = Core.ImportHashed { Core.hash = Nothing , Core.importType = Core.Local Core.Here $ Core.File { Core.directory = Core.Directory ["deep-nested-large-record", "benchmark"] , Core.file = "prelude.dhall" } } } issue412 :: Core.Expr s TypeCheck.X -> Criterion.Benchmarkable issue412 prelude = Criterion.whnf TypeCheck.typeOf expr where expr = Core.Let (pure (Core.Binding "prelude" Nothing prelude)) $ Core.ListLit Nothing $ Seq.replicate 5 $ Core.Var (Core.V "prelude" 0) `Core.Field` "types" `Core.Field` "Little" `Core.Field` "Foo" unionPerformance :: Core.Expr s TypeCheck.X -> Criterion.Benchmarkable unionPerformance prelude = Criterion.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" main :: IO () main = do prelude <- Import.load (Core.Embed dhallPreludeImport) defaultMain [ Criterion.bench "issue 412" (issue412 prelude) , Criterion.bench "union performance" (unionPerformance prelude) ] dhall-1.19.1/benchmark/deep-nested-large-record/prelude.dhall0000644000000000000000000000014413377175666022242 0ustar0000000000000000{ types = { Big = constructors ./BigEnum.dhall , Little = constructors ./LittleEnum.dhall } } dhall-1.19.1/benchmark/dhall-command/0000755000000000000000000000000013377175666015534 5ustar0000000000000000dhall-1.19.1/benchmark/dhall-command/Main.hs0000644000000000000000000000062313377175666016755 0ustar0000000000000000 {-# 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 False , Main.explain = False , Main.plain = False , Main.ascii = False , Main.standardVersion = defaultStandardVersion } main :: IO () main = do Main.command options dhall-1.19.1/benchmark/examples/0000755000000000000000000000000013377175666014652 5ustar0000000000000000dhall-1.19.1/benchmark/examples/issue108.dhall0000644000000000000000000001111313377175666017236 0ustar0000000000000000λ(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) "" dhall-1.19.1/benchmark/parser/0000755000000000000000000000000013377175666014330 5ustar0000000000000000dhall-1.19.1/benchmark/parser/Main.hs0000644000000000000000000000717613377175666015563 0ustar0000000000000000{-# LANGUAGE CPP #-} {-# 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 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 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 type PreludeFiles = Map FilePath T.Text loadPreludeFiles :: IO PreludeFiles loadPreludeFiles = loadDirectory "Prelude" where loadDirectory :: FilePath -> IO PreludeFiles loadDirectory dir = withCurrentDirectory dir $ do files <- getCurrentDirectory >>= listDirectory results <- forM files $ \file -> do file' <- makeAbsolute file doesExist <- doesFileExist file' if doesExist then loadFile file' else loadDirectory file' pure $ unions results loadFile :: FilePath -> IO PreludeFiles loadFile path = singleton path <$> TIO.readFile path benchParser :: PreludeFiles -> Criterion.Benchmark benchParser = bgroup "exprFromText" . foldrWithKey (\name expr -> (benchExprFromText name expr :)) [] benchExprFromText :: String -> T.Text -> Criterion.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) where f bytes = do term <- case Codec.Serialise.deserialiseOrFail bytes of Left _ -> Nothing Right term -> return term case Dhall.Binary.decodeWithVersion term of Left _ -> Nothing Right expression -> return expression 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 " " <> "-}") , benchExprFromText "Deeply nested parentheses" "((((((((((((((((x))))))))))))))))" , benchParser prelude ] dhall-1.19.1/dhall/0000755000000000000000000000000013377175666012166 5ustar0000000000000000dhall-1.19.1/dhall/Main.hs0000644000000000000000000000012513377175666013404 0ustar0000000000000000module Main where import qualified Dhall.Main main :: IO () main = Dhall.Main.main dhall-1.19.1/doctest/0000755000000000000000000000000013377175666012547 5ustar0000000000000000dhall-1.19.1/doctest/Main.hs0000644000000000000000000000156113377175666013772 0ustar0000000000000000module Main where import Data.Monoid ((<>)) import System.FilePath (()) import qualified System.Directory import qualified Test.Mockery.Directory import qualified Test.DocTest main :: IO () main = do pwd <- System.Directory.getCurrentDirectory prefix <- System.Directory.makeAbsolute pwd Test.Mockery.Directory.inTempDirectory $ do writeFile "makeBools" "λ(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" Test.DocTest.doctest [ "--fast" , "-i" <> (prefix "src") , prefix "src/Dhall.hs" , prefix "src/Dhall/Import.hs" , prefix "src/Dhall/Tutorial.hs" ] dhall-1.19.1/Prelude/0000755000000000000000000000000013377175666012502 5ustar0000000000000000dhall-1.19.1/Prelude/Monoid0000644000000000000000000000025513377175666013654 0ustar0000000000000000https://raw.githubusercontent.com/dhall-lang/Prelude/a22da69657b9316a3c51ba0bf80c9d4024db3fce/Monoid sha256:c4ff4f04ce9d3b7b579ff2ac7fe00258d665c701f895493b73082b750b28553d dhall-1.19.1/Prelude/package.dhall0000644000000000000000000000026413377175666015105 0ustar0000000000000000https://raw.githubusercontent.com/dhall-lang/Prelude/e9c90396c02f9eb0fe66c00c544615cbfa068f34/package.dhall sha256:534e4a9e687ba74bfac71b30fc27aa269c0465087ef79bf483e876781602a454 dhall-1.19.1/src/0000755000000000000000000000000013377175666011671 5ustar0000000000000000dhall-1.19.1/src/Dhall.hs0000644000000000000000000012471313377175666013261 0ustar0000000000000000{-# LANGUAGE DefaultSignatures #-} {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TypeOperators #-} {-| Please read the "Dhall.Tutorial" module, which contains a tutorial explaining how to use the language, the compiler, and this library -} module Dhall ( -- * Input input , inputWithSettings , inputFile , inputFileWithSettings , inputExpr , inputExprWithSettings , rootDirectory , sourceName , startingContext , normalizer , standardVersion , defaultInputSettings , InputSettings , defaultEvaluateSettings , EvaluateSettings , HasEvaluateSettings , detailed -- * Types , Type(..) , RecordType(..) , InputType(..) , Interpret(..) , InvalidType(..) , auto , genericAuto , InterpretOptions(..) , defaultInterpretOptions , bool , natural , integer , scientific , double , lazyText , strictText , maybe , sequence , list , vector , unit , string , pair , record , field , GenericInterpret(..) , GenericInject(..) , Inject(..) , inject , RecordInputType(..) , inputFieldWith , inputField , inputRecord -- * Miscellaneous , rawInput , (>$<) , (>*<) -- * Re-exports , Natural , Seq , Text , Vector , Generic ) where import Control.Applicative (empty, liftA2, (<|>), Alternative) import Control.Exception (Exception) import Control.Monad.Trans.State.Strict import Data.Functor.Contravariant (Contravariant(..), (>$<)) import Data.Functor.Contravariant.Divisible (Divisible(..), divided) import Data.Monoid ((<>)) import Data.Scientific (Scientific) import Data.Sequence (Seq) import Data.Text (Text) 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.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 -- $setup -- >>> :set -XOverloadedStrings throws :: Exception e => Either e a -> IO a throws (Left e) = Control.Exception.throwIO e throws (Right r) = return r {-| Every `Type` must obey the contract that if an expression's type matches the the `expected` type then the `extract` function must succeed. If not, then this exception is thrown This exception indicates that an invalid `Type` was provided to the `input` function -} data InvalidType = InvalidType deriving (Typeable) _ERROR :: String _ERROR = "\ESC[1;31mError\ESC[0m" instance Show InvalidType where show InvalidType = _ERROR <> ": Invalid Dhall.Type \n\ \ \n\ \Every Type must provide an extract function that succeeds if an expression \n\ \matches the expected type. You provided a Type that disobeys this contract \n" instance Exception InvalidType -- | @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 :: 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 = Dhall.Core.ReifiedNormalizer (const (pure 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 (Dhall.Core.ReifiedNormalizer X) normalizer = evaluateSettings . l where l :: (Functor f) => LensLike' f EvaluateSettings (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 <- 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 _ <- throws (Dhall.TypeCheck.typeWith (view startingContext settings) annot) case extract (Dhall.Core.normalizeWith (Dhall.Core.getReifiedNormalizer (view normalizer settings)) expr') of Just x -> return x Nothing -> Control.Exception.throwIO InvalidType {-| 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 <- 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 _ <- throws (Dhall.TypeCheck.typeWith (view startingContext settings) expr') pure (Dhall.Core.normalizeWith (Dhall.Core.getReifiedNormalizer (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 extractOut e = Just (\i -> case extractIn (Dhall.Core.normalize (App e (embed i))) of Just o -> o Nothing -> error "Interpret: You cannot decode a function if it does not have the correct type" ) expectedOut = Pi "_" declared expectedIn InputType {..} = inject Type extractIn expectedIn = autoWith opts instance (Interpret a, Interpret b) => Interpret (a, b) {-| Use the default options for interpreting a configuration file > auto = autoWith defaultInterpretOptions -} auto :: Interpret a => Type a auto = autoWith defaultInterpretOptions {-| `genericAuto` is the default implementation for `auto` if you derive `Interpret`. The difference is that you can use `genericAuto` without having to explicitly provide an `Interpret` instance for a type as long as the type derives `Generic` -} genericAuto :: (Generic a, GenericInterpret (Rep a)) => Type a genericAuto = fmap to (evalState (genericAutoWith defaultInterpretOptions) 1) {-| Use these options to tweak how Dhall derives a generic implementation of `Interpret` -} data InterpretOptions = InterpretOptions { fieldModifier :: Text -> Text -- ^ Function used to transform Haskell field names into their corresponding -- Dhall field names , constructorModifier :: Text -> Text -- ^ Function used to transform Haskell constructor names into their -- corresponding Dhall alternative names } {-| Default interpret options, which you can tweak or override, like this: > autoWith > (defaultInterpretOptions { fieldModifier = Data.Text.Lazy.dropWhile (== '_') }) -} defaultInterpretOptions :: InterpretOptions defaultInterpretOptions = InterpretOptions { fieldModifier = id , constructorModifier = id } {-| This is the underlying class that powers the `Interpret` class's support for automatically deriving a generic implementation -} class GenericInterpret f where genericAutoWith :: InterpretOptions -> State Int (Type (f a)) instance GenericInterpret f => GenericInterpret (M1 D d f) where genericAutoWith options = do res <- genericAutoWith options pure (fmap M1 res) instance GenericInterpret V1 where genericAutoWith _ = pure Type {..} where extract _ = Nothing expected = Union mempty 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 (UnionLit name e _) | name == nameL = fmap (L1 . M1) (extractL e) | name == nameR = fmap (R1 . M1) (extractR e) | otherwise = Nothing extract _ = Nothing expected = Union (Dhall.Map.fromList [(nameL, expectedL), (nameR, expectedR)]) Type extractL expectedL = evalState (genericAutoWith options) 1 Type extractR expectedR = evalState (genericAutoWith options) 1 instance (Constructor c, GenericInterpret (f :+: g), GenericInterpret h) => GenericInterpret ((f :+: g) :+: M1 C c h) where genericAutoWith options@(InterpretOptions {..}) = pure (Type {..}) where n :: M1 i c h a n = undefined name = constructorModifier (Data.Text.pack (conName n)) extract u@(UnionLit name' e _) | name == name' = fmap (R1 . M1) (extractR e) | otherwise = fmap L1 (extractL u) extract _ = Nothing expected = Union (Dhall.Map.insert name expectedR expectedL) Type extractL (Union expectedL) = evalState (genericAutoWith options) 1 Type extractR expectedR = evalState (genericAutoWith options) 1 instance (Constructor c, GenericInterpret f, GenericInterpret (g :+: h)) => GenericInterpret (M1 C c f :+: (g :+: h)) where genericAutoWith options@(InterpretOptions {..}) = pure (Type {..}) where n :: M1 i c f a n = undefined name = constructorModifier (Data.Text.pack (conName n)) extract u@(UnionLit name' e _) | name == name' = fmap (L1 . M1) (extractL e) | otherwise = fmap R1 (extractR u) extract _ = Nothing expected = Union (Dhall.Map.insert name expectedL expectedR) Type extractL expectedL = evalState (genericAutoWith options) 1 Type extractR (Union expectedR) = evalState (genericAutoWith options) 1 instance (GenericInterpret (f :+: g), GenericInterpret (h :+: i)) => GenericInterpret ((f :+: g) :+: (h :+: i)) where genericAutoWith options = pure (Type {..}) where extract e = fmap L1 (extractL e) <|> fmap R1 (extractR e) expected = Union (Dhall.Map.union expectedL expectedR) Type extractL (Union expectedL) = evalState (genericAutoWith options) 1 Type extractR (Union expectedR) = evalState (genericAutoWith options) 1 instance GenericInterpret f => GenericInterpret (M1 C c f) where genericAutoWith options = do res <- genericAutoWith options pure (fmap M1 res) instance GenericInterpret U1 where genericAutoWith _ = pure (Type {..}) where extract _ = Just U1 expected = Record (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 Record ktsL = expectedL let Record ktsR = 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 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)) = UnionLit keyL (embedL l) (Dhall.Map.singleton keyR declaredR) embed (R1 (M1 r)) = UnionLit keyR (embedR r) (Dhall.Map.singleton keyL declaredL) declared = Union (Dhall.Map.fromList [(keyL, declaredL), (keyR, declaredR)]) nL :: M1 i c1 f1 a nL = undefined nR :: M1 i c2 f2 a nR = undefined keyL = constructorModifier (Data.Text.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) = UnionLit keyL valL (Dhall.Map.insert keyR declaredR ktsL') where UnionLit keyL valL ktsL' = embedL l embed (R1 (M1 r)) = UnionLit keyR (embedR r) ktsL nR :: M1 i c h a nR = undefined keyR = constructorModifier (Data.Text.pack (conName nR)) declared = Union (Dhall.Map.insert keyR declaredR ktsL) InputType embedL (Union ktsL) = evalState (genericInjectWith options) 1 InputType embedR declaredR = evalState (genericInjectWith options) 1 instance (Constructor c, GenericInject f, GenericInject (g :+: h)) => GenericInject (M1 C c f :+: (g :+: h)) where genericInjectWith options@(InterpretOptions {..}) = pure (InputType {..}) where embed (L1 (M1 l)) = UnionLit keyL (embedL l) ktsR embed (R1 r) = UnionLit keyR valR (Dhall.Map.insert keyL declaredL ktsR') where UnionLit keyR valR ktsR' = embedR r nL :: M1 i c f a nL = undefined keyL = constructorModifier (Data.Text.pack (conName nL)) declared = Union (Dhall.Map.insert keyL declaredL ktsR) InputType embedL declaredL = evalState (genericInjectWith options) 1 InputType embedR (Union ktsR) = evalState (genericInjectWith options) 1 instance (GenericInject (f :+: g), GenericInject (h :+: i)) => GenericInject ((f :+: g) :+: (h :+: i)) where genericInjectWith options = pure (InputType {..}) where embed (L1 l) = UnionLit keyL valR (Dhall.Map.union ktsL' ktsR) where UnionLit keyL valR ktsL' = embedL l embed (R1 r) = UnionLit keyR valR (Dhall.Map.union ktsL ktsR') where UnionLit keyR valR ktsR' = embedR r declared = Union (Dhall.Map.union ktsL ktsR) InputType embedL (Union ktsL) = evalState (genericInjectWith options) 1 InputType embedR (Union ktsR) = evalState (genericInjectWith options) 1 instance (GenericInject f, GenericInject g) => GenericInject (f :*: g) where genericInjectWith options = do InputType embedInL declaredInL <- genericInjectWith options InputType embedInR declaredInR <- genericInjectWith options let embed (l :*: r) = RecordLit (Dhall.Map.union mapL mapR) where RecordLit mapL = embedInL l RecordLit mapR = embedInR r let declared = Record (Dhall.Map.union mapL mapR) where Record mapL = declaredInL Record mapR = 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" string > <*> field "description" string > <*> 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 '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 dhall-1.19.1/src/Dhall/0000755000000000000000000000000013377175666012715 5ustar0000000000000000dhall-1.19.1/src/Dhall/Binary.hs0000644000000000000000000005600313377175666014501 0ustar0000000000000000{-# 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 -- * Encoding and decoding , encodeWithVersion , decodeWithVersion -- * 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 Codec.CBOR.Magic (floatToWord16, wordToFloat16) import qualified Data.Sequence import qualified Data.Text import qualified Dhall.Map import qualified Dhall.Set import qualified Options.Applicative -- | Supported version strings data StandardVersion = V_4_0_0 -- ^ Version "4.0.0" defaultStandardVersion :: StandardVersion defaultStandardVersion = V_4_0_0 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 "4.0.0" -> return V_4_0_0 _ -> fail "Unsupported version" {-| 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 baseFunction = (baseFunction, id) encode :: Expr s Import -> Term encode (Var (V "_" n)) = TInteger n encode (Var (V x 0)) = TString x 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 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 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 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₀ xs₀) = TList ([ TInt 10, t₁ ] ++ xs₁) where t₁ = encode t₀ xs₁ = map TString (Dhall.Set.toList xs₀) encode (Union xTs₀) = TList [ TInt 11, TMap xTs₁ ] where xTs₁ = do (x₀, _T₀) <- Dhall.Map.toList xTs₀ let x₁ = TString x₀ let _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₀, _T₀) <- Dhall.Map.toList yTs₀ let y₁ = TString y₀ let _T₁ = encode _T₀ return (y₁, _T₁) encode (Constructors u₀) = TList [ TInt 13, u₁ ] where u₁ = encode u₀ 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 n16 = floatToWord16 n32 useFloat = n64 == float2Double n32 useHalf = n64 == (float2Double . wordToFloat16 . fromIntegral) n16 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) = importToTerm 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 importToTerm :: Import -> Term importToTerm import_ = case importType of Remote (URL { scheme = scheme₀, ..}) -> TList ( [ TInt 24, TInt scheme₁, TString authority ] ++ map TString (reverse components) ++ [ TString file ] ++ (case query of Nothing -> [ TNull ]; Just q -> [ TString q ]) ++ (case fragment of Nothing -> [ TNull ]; Just f -> [ TString f ]) ) where scheme₁ = case scheme₀ of HTTP -> 0 HTTPS -> 1 File {..} = path Directory {..} = directory Local prefix₀ path -> TList ( [ TInt 24, TInt prefix₁ ] ++ map TString components₁ ++ [ TString file ] ) where File {..} = path Directory {..} = directory (prefix₁, components₁) = case (prefix₀, reverse components) of (Absolute, rest ) -> (2, rest) (Here , ".." : rest) -> (4, rest) (Here , rest ) -> (3, rest) (Home , rest ) -> (5, rest) Env x -> TList [ TInt 24, TInt 6, TString x ] Missing -> TList [ TInt 24, TInt 7 ] where Import {..} = import_ ImportHashed {..} = importHashed decode :: Term -> Maybe (Expr s Import) 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 "List") = return List decode (TString "Type") = return (Const Type) decode (TString "Kind") = return (Const Kind) decode (TString "Sort") = return (Const Sort) decode (TString x) = return (Var (V x 0)) 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 process (TString x) = return x process _ = empty xs₀ <- traverse process xs₁ return (Project t₀ (Dhall.Set.fromList xs₀)) decode (TList [ TInt 11, TMap xTs₁ ]) = do let process (TString x, _T₁) = do _T₀ <- decode _T₁ return (x, _T₀) 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₀ <- decode _T₁ return (y, _T₀) process _ = empty yTs₀ <- traverse process yTs₁ return (UnionLit x t₀ (Dhall.Map.fromList yTs₀)) decode (TList [ TInt 13, u₁ ]) = do u₀ <- decode u₁ return (Constructors u₀) 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 (TList (TInt 24 : TInt n : xs)) = do let remote scheme = do let process [ TString file, q, f ] = do query <- case q of TNull -> return Nothing TString x -> return (Just x) _ -> empty fragment <- case f of TNull -> return Nothing TString x -> return (Just x) _ -> empty return ([], file, query, fragment) process (TString path : ys) = do (paths, file, query, fragment) <- process ys return (path : paths, file, query, fragment) process _ = do empty (authority, paths, file, query, fragment) <- case xs of TString authority : ys -> do (paths, file, query, fragment) <- process ys return (authority, paths, file, query, fragment) _ -> empty let components = reverse paths let directory = Directory {..} let path = File {..} let headers = Nothing 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 finalPaths = case n of 4 -> ".." : paths _ -> paths let components = reverse finalPaths 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 Here 5 -> local Home 6 -> env 7 -> missing _ -> empty let hash = Nothing let importHashed = ImportHashed {..} let importMode = Code return (Embed (Import {..})) 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 {-| Decode a Dhall expression This auto-detects which standard version to decode based on the included standard version string in the decoded expression -} decodeWithVersion :: Term -> Either DecodingFailure (Expr s Import) decodeWithVersion term = do (version, subTerm) <- case term of TList [ TString version, subTerm ] -> return (version, subTerm) _ -> fail ("Cannot decode the version from this decoded CBOR expression: " <> show term) case version of "4.0.0" -> do return () _ -> do fail ("This decoded version is not supported: " <> Data.Text.unpack version) case decode subTerm of Nothing -> fail ("This decoded CBOR expression does not represent a valid Dhall expression: " <> show subTerm) Just expression -> return expression -- | Encode a Dhall expression using the specified `Version` encodeWithVersion :: StandardVersion -> Expr s Import -> Term encodeWithVersion V_4_0_0 expression = TList [ TString "4.0.0", encode expression ] data DecodingFailure = CannotDecodeVersionString Term | UnsupportedVersionString Text | CBORIsNotDhall Term deriving (Eq) instance Exception DecodingFailure _ERROR :: String _ERROR = "\ESC[1;31mError\ESC[0m" instance Show DecodingFailure where show (CannotDecodeVersionString term) = _ERROR <> ": Cannot decode version string\n" <> "\n" <> "This CBOR expression does not contain a version string in any\n" <> "recognizable format\n" <> "\n" <> "↳ " <> show term <> "\n" show (UnsupportedVersionString version) = _ERROR <> ": Unsupported version string\n" <> "\n" <> "The encoded Dhall expression was tagged with a version string of:\n" <> "\n" <> "↳ " <> show version <> "\n" <> "\n" <> "... but this implementation cannot decode that version\n" <> "\n" <> "Some common reasons why you might get this error:\n" <> "\n" <> "● You are using an old version of the interpreter and need to upgrade\n" 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" dhall-1.19.1/src/Dhall/Context.hs0000644000000000000000000000426313377175666014702 0ustar0000000000000000{-# LANGUAGE DeriveFunctor #-} -- | This is a utility module that consolidates all `Context`-related operations module Dhall.Context ( -- * Context Context , empty , insert , match , lookup , toList ) where import Data.Text (Text) import Prelude hiding (lookup) {-| A @(Context a)@ associates `Text` labels with values of type @a@. Each `Text` label can correspond to multiple values of type @a@ The `Context` is used for type-checking when @(a = Expr X)@ * You create a `Context` using `empty` and `insert` * You transform a `Context` using `fmap` * You consume a `Context` using `lookup` and `toList` The difference between a `Context` and a `Data.Map.Map` is that a `Context` lets you have multiple ordered occurrences of the same key and you can query for the @n@th occurrence of a given key. -} newtype Context a = Context { getContext :: [(Text, a)] } deriving (Functor) -- | An empty context with no key-value pairs empty :: Context a empty = Context [] -- | Add a key-value pair to the `Context` insert :: Text -> a -> Context a -> Context a insert k v (Context kvs) = Context ((k, v) : kvs) {-# INLINABLE insert #-} {-| \"Pattern match\" on a `Context` > match (insert k v ctx) = Just (k, v, ctx) > match empty = Nothing -} match :: Context a -> Maybe (Text, a, Context a) match (Context ((k, v) : kvs)) = Just (k, v, Context kvs) match (Context [] ) = Nothing {-# INLINABLE match #-} {-| Look up a key by name and index > lookup _ _ empty = Nothing > lookup k 0 (insert k v c) = Just v > lookup k n (insert k v c) = lookup k (n - 1) c > lookup k n (insert j v c) = lookup k n c -- k /= j -} lookup :: Text -> Integer -> Context a -> Maybe a lookup _ _ (Context [] ) = Nothing lookup x n (Context ((k, v):kvs)) = if x == k then if n == 0 then Just v else lookup x (n - 1) (Context kvs) else lookup x n (Context kvs) {-# INLINABLE lookup #-} {-| Return all key-value associations as a list > toList empty = [] > toList (insert k v ctx) = (k, v) : toList ctx -} toList :: Context a -> [(Text, a)] toList = getContext {-# INLINABLE toList #-} dhall-1.19.1/src/Dhall/Core.hs0000644000000000000000000025151013377175666014145 0ustar0000000000000000{-# 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(..) , Path , Scheme(..) , Var(..) , Binding(..) , Chunks(..) , Expr(..) -- * Normalization , alphaNormalize , normalize , normalizeWith , normalizeWithM , Normalizer , NormalizerM , ReifiedNormalizer (..) , judgmentallyEqual , subst , shift , isNormalized , isNormalizedWith , denote , freeIn -- * Pretty-printing , pretty -- * Miscellaneous , internalError , reservedIdentifiers , escapeText , subExpressions , pathCharacter ) where #if MIN_VERSION_base(4,8,0) #else import Control.Applicative (Applicative(..), (<$>)) #endif import Control.Applicative (empty) import Crypto.Hash (SHA256) import Data.Bifunctor (Bifunctor(..)) import Data.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 {-# SOURCE #-} Dhall.Pretty.Internal import GHC.Generics (Generic) import Numeric.Natural (Natural) import Prelude hiding (succ) import qualified Control.Monad import qualified Crypto.Hash 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 {-| 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, 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 @.@ | Home -- ^ Path relative to @~@ deriving (Eq, Generic, Ord, Show) instance Pretty FilePrefix where pretty Absolute = "" pretty Here = "." pretty Home = "~" data Scheme = HTTP | HTTPS deriving (Eq, Generic, Ord, Show) data URL = URL { scheme :: Scheme , authority :: Text , path :: File , query :: Maybe Text , fragment :: Maybe Text , headers :: Maybe ImportHashed } deriving (Eq, Generic, Ord, Show) -- | 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) 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₁, ..}) import₀ <> Remote (URL { headers = headers₀, .. }) = Remote (URL { headers = headers₁, .. }) where importHashed₀ = ImportHashed Nothing import₀ headers₁ = fmap (importHashed₀ <>) headers₀ _ <> import₁ = import₁ instance Pretty ImportType where pretty (Local prefix file) = Pretty.pretty prefix <> Pretty.pretty file pretty (Remote (URL {..})) = schemeDoc <> "://" <> Pretty.pretty authority <> Pretty.pretty path <> queryDoc <> fragmentDoc <> foldMap prettyHeaders headers where prettyHeaders h = " using " <> Pretty.pretty h schemeDoc = case scheme of HTTP -> "http" HTTPS -> "https" queryDoc = case query of Nothing -> "" Just q -> "?" <> Pretty.pretty q fragmentDoc = case fragment of Nothing -> "" Just f -> "#" <> Pretty.pretty f 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 -> "" -- | Type synonym for `Import`, provided for backwards compatibility type Path = Import {-# DEPRECATED Path "Use Dhall.Core.Import instead" #-} {-| 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, 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) -- | > 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, t1), (k2, t2)] ~ < k1 : t1 | k2 : t2 > | Union (Map Text (Expr s a)) -- | > UnionLit k v [(k1, t1), (k2, t2)] ~ < k = v | k1 : t1 | k2 : t2 > | UnionLit Text (Expr s a) (Map Text (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)) -- | > Constructors e ~ constructors e | Constructors (Expr s a) -- | > Field e x ~ e.x | Field (Expr s a) Text -- | > Project e xs ~ e.{ xs } | Project (Expr s a) (Set Text) -- | > 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, 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 _ 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 f) u) fmap f (UnionLit v e u) = UnionLit v (fmap f e) (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 (Constructors e1) = Constructors (fmap f e1) fmap f (Field e1 v) = Field (fmap f e1) v fmap f (Project e1 vs) = Project (fmap f e1) 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) 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 (>>= k) a) UnionLit a b c >>= k = UnionLit a (b >>= k) (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) Constructors a >>= k = Constructors (a >>= k) Field a b >>= k = Field (a >>= k) b Project a b >>= k = Project (a >>= 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 _ 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 (first k) a) first k (UnionLit a b c ) = UnionLit a (first k b) (fmap (first k) c) first k (Combine a b ) = Combine (first k a) (first k b) first k (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 (Constructors a ) = Constructors (first k a) first k (Field a b ) = Field (first k a) b first k (Project a b ) = Project (first k a) 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, 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, 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₀) = Let (Binding x₁ mA₁ a₁ :| (l₁ : ls₁)) 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₀ Let (l₁ :| ls₁) b₁ = shift d (V x₀ n₁) (Let (l₀ :| ls₀) b₀) 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 _ _ 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 (shift d v) a shift d v (UnionLit a b c) = UnionLit a b' c' where b' = shift d v b c' = fmap (shift d v) c shift d v (Combine a b) = Combine a' b' where a' = shift d v a b' = shift d v b shift d v (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 (Constructors a) = Constructors a' where a' = shift d v a shift d v (Field a b) = Field a' b where a' = shift d v a shift d v (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₀) = Let (Binding x₁ mA₁ a₁ :| (l₁ : ls₁)) 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₀ Let (l₁ :| ls₁) b₁ = subst (V x₀ n₁) e₁ (Let (l₀ :| ls₀) b₀) 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 _ _ 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 (fmap (subst x e) kts) subst x e (RecordLit kvs) = RecordLit (fmap (subst x e) kvs) subst x e (Union kts) = Union (fmap (subst x e) kts) subst x e (UnionLit a b kts) = UnionLit a (subst x e b) (fmap (subst x e) kts) subst x e (Combine a b) = Combine a' b' where a' = subst x e a b' = subst x e b subst x e (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 (Constructors a) = Constructors a' where a' = subst x e a subst x e (Field a b) = Field a' b where a' = subst x e a subst x e (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 (Const c) = Const c alphaNormalize (Var v) = Var v alphaNormalize (Lam "_" _A₀ b₀) = Lam "_" _A₁ b₁ where _A₁ = alphaNormalize _A₀ b₁ = alphaNormalize b₀ alphaNormalize (Lam x _A₀ b₀) = Lam "_" _A₁ b₄ where _A₁ = alphaNormalize _A₀ b₁ = shift 1 (V "_" 0) b₀ b₂ = subst (V x 0) (Var (V "_" 0)) b₁ b₃ = shift (-1) (V x 0) b₂ b₄ = alphaNormalize b₃ alphaNormalize (Pi "_" _A₀ _B₀) = Pi "_" _A₁ _B₁ where _A₁ = alphaNormalize _A₀ _B₁ = alphaNormalize _B₀ alphaNormalize (Pi x _A₀ _B₀) = Pi "_" _A₁ _B₄ where _A₁ = alphaNormalize _A₀ _B₁ = shift 1 (V "_" 0) _B₀ _B₂ = subst (V x 0) (Var (V "_" 0)) _B₁ _B₃ = shift (-1) (V x 0) _B₂ _B₄ = alphaNormalize _B₃ alphaNormalize (App f₀ a₀) = App f₁ a₁ where f₁ = alphaNormalize f₀ a₁ = alphaNormalize a₀ alphaNormalize (Let (Binding "_" mA₀ a₀ :| []) b₀) = Let (Binding "_" mA₁ a₁ :| []) b₁ where mA₁ = fmap alphaNormalize mA₀ a₁ = alphaNormalize a₀ b₁ = alphaNormalize b₀ alphaNormalize (Let (Binding "_" mA₀ a₀ :| (l₀ : ls₀)) b₀) = Let (Binding "_" mA₁ a₁ :| (l₁ : ls₁)) b₁ where mA₁ = fmap alphaNormalize mA₀ a₁ = alphaNormalize a₀ Let (l₁ :| ls₁) b₁ = alphaNormalize (Let (l₀ :| ls₀) b₀) alphaNormalize (Let (Binding x mA₀ a₀ :| []) b₀) = Let (Binding "_" mA₁ a₁ :| []) b₄ where mA₁ = fmap alphaNormalize mA₀ a₁ = alphaNormalize a₀ b₁ = shift 1 (V "_" 0) b₀ b₂ = subst (V x 0) (Var (V "_" 0)) b₁ b₃ = shift (-1) (V x 0) b₂ b₄ = alphaNormalize b₃ alphaNormalize (Let (Binding x mA₀ a₀ :| (l₀ : ls₀)) b₀) = Let (Binding "_" mA₁ a₁ :| (l₁ : ls₁)) b₄ where mA₁ = fmap alphaNormalize mA₀ a₁ = alphaNormalize a₀ b₁ = shift 1 (V "_" 0) b₀ b₂ = subst (V x 0) (Var (V "_" 0)) b₁ b₃ = shift (-1) (V x 0) b₂ Let (l₁ :| ls₁) b₄ = alphaNormalize (Let (l₀ :| ls₀) b₃) alphaNormalize (Annot t₀ _T₀) = Annot t₁ _T₁ where t₁ = alphaNormalize t₀ _T₁ = alphaNormalize _T₀ alphaNormalize Bool = Bool alphaNormalize (BoolLit b) = BoolLit b alphaNormalize (BoolAnd l₀ r₀) = BoolAnd l₁ r₁ where l₁ = alphaNormalize l₀ r₁ = alphaNormalize r₀ alphaNormalize (BoolOr l₀ r₀) = BoolOr l₁ r₁ where l₁ = alphaNormalize l₀ r₁ = alphaNormalize r₀ alphaNormalize (BoolEQ l₀ r₀) = BoolEQ l₁ r₁ where l₁ = alphaNormalize l₀ r₁ = alphaNormalize r₀ alphaNormalize (BoolNE l₀ r₀) = BoolNE l₁ r₁ where l₁ = alphaNormalize l₀ r₁ = alphaNormalize r₀ alphaNormalize (BoolIf t₀ l₀ r₀) = BoolIf t₁ l₁ r₁ where t₁ = alphaNormalize t₀ l₁ = alphaNormalize l₀ r₁ = alphaNormalize r₀ alphaNormalize Natural = Natural alphaNormalize (NaturalLit n) = NaturalLit n alphaNormalize NaturalFold = NaturalFold alphaNormalize NaturalBuild = NaturalBuild alphaNormalize NaturalIsZero = NaturalIsZero alphaNormalize NaturalEven = NaturalEven alphaNormalize NaturalOdd = NaturalOdd alphaNormalize NaturalToInteger = NaturalToInteger alphaNormalize NaturalShow = NaturalShow alphaNormalize (NaturalPlus l₀ r₀) = NaturalPlus l₁ r₁ where l₁ = alphaNormalize l₀ r₁ = alphaNormalize r₀ alphaNormalize (NaturalTimes l₀ r₀) = NaturalTimes l₁ r₁ where l₁ = alphaNormalize l₀ r₁ = alphaNormalize r₀ alphaNormalize Integer = Integer alphaNormalize (IntegerLit n) = IntegerLit n alphaNormalize IntegerShow = IntegerShow alphaNormalize IntegerToDouble = IntegerToDouble alphaNormalize Double = Double alphaNormalize (DoubleLit n) = DoubleLit n alphaNormalize DoubleShow = DoubleShow alphaNormalize Text = Text alphaNormalize (TextLit (Chunks xys₀ z)) = TextLit (Chunks xys₁ z) where xys₁ = do (x, y₀) <- xys₀ let y₁ = alphaNormalize y₀ return (x, y₁) alphaNormalize (TextAppend l₀ r₀) = TextAppend l₁ r₁ where l₁ = alphaNormalize l₀ r₁ = alphaNormalize r₀ alphaNormalize List = List alphaNormalize (ListLit (Just _T₀) ts₀) = ListLit (Just _T₁) ts₁ where _T₁ = alphaNormalize _T₀ ts₁ = fmap alphaNormalize ts₀ alphaNormalize (ListLit Nothing ts₀) = ListLit Nothing ts₁ where ts₁ = fmap alphaNormalize ts₀ alphaNormalize (ListAppend l₀ r₀) = ListAppend l₁ r₁ where l₁ = alphaNormalize l₀ r₁ = alphaNormalize r₀ alphaNormalize ListBuild = ListBuild alphaNormalize ListFold = ListFold alphaNormalize ListLength = ListLength alphaNormalize ListHead = ListHead alphaNormalize ListLast = ListLast alphaNormalize ListIndexed = ListIndexed alphaNormalize ListReverse = ListReverse alphaNormalize Optional = Optional alphaNormalize (OptionalLit _T₀ ts₀) = OptionalLit _T₁ ts₁ where _T₁ = alphaNormalize _T₀ ts₁ = fmap alphaNormalize ts₀ alphaNormalize (Some a₀) = Some a₁ where a₁ = alphaNormalize a₀ alphaNormalize None = None alphaNormalize OptionalFold = OptionalFold alphaNormalize OptionalBuild = OptionalBuild alphaNormalize (Record kts₀) = Record kts₁ where kts₁ = fmap alphaNormalize kts₀ alphaNormalize (RecordLit kvs₀) = RecordLit kvs₁ where kvs₁ = fmap alphaNormalize kvs₀ alphaNormalize (Union kts₀) = Union kts₁ where kts₁ = fmap alphaNormalize kts₀ alphaNormalize (UnionLit k v₀ kts₀) = UnionLit k v₁ kts₁ where v₁ = alphaNormalize v₀ kts₁ = fmap alphaNormalize kts₀ alphaNormalize (Combine l₀ r₀) = Combine l₁ r₁ where l₁ = alphaNormalize l₀ r₁ = alphaNormalize r₀ alphaNormalize (CombineTypes l₀ r₀) = CombineTypes l₁ r₁ where l₁ = alphaNormalize l₀ r₁ = alphaNormalize r₀ alphaNormalize (Prefer l₀ r₀) = Prefer l₁ r₁ where l₁ = alphaNormalize l₀ r₁ = alphaNormalize r₀ alphaNormalize (Merge t₀ u₀ _T₀) = Merge t₁ u₁ _T₁ where t₁ = alphaNormalize t₀ u₁ = alphaNormalize u₀ _T₁ = fmap alphaNormalize _T₀ alphaNormalize (Constructors u₀) = Constructors u₁ where u₁ = alphaNormalize u₀ alphaNormalize (Field e₀ a) = Field e₁ a where e₁ = alphaNormalize e₀ alphaNormalize (Project e₀ a) = Project e₁ a where e₁ = alphaNormalize e₀ alphaNormalize (Note s e₀) = Note s e₁ where e₁ = alphaNormalize e₀ alphaNormalize (ImportAlt l₀ r₀) = ImportAlt l₁ r₁ where l₁ = alphaNormalize l₀ r₁ = alphaNormalize r₀ alphaNormalize (Embed a) = Embed a {-| Reduce an expression to its normal form, performing beta reduction `normalize` does not type-check the expression. You may want to type-check expressions before normalizing them since normalization can convert an ill-typed expression into a well-typed expression. However, `normalize` will not fail if the expression is ill-typed and will leave ill-typed sub-expressions unevaluated. -} normalize :: Eq a => Expr s a -> Expr t a normalize = normalizeWith (const (pure Nothing)) {-| This function is used to determine whether folds like @Natural/fold@ or @List/fold@ should be lazy or strict in their accumulator based on the type of the accumulator If this function returns `True`, then they will be strict in their accumulator since we can guarantee an upper bound on the amount of work to normalize the accumulator on each step of the loop. If this function returns `False` then they will be lazy in their accumulator and only normalize the final result at the end of the fold -} boundedType :: Expr s a -> Bool boundedType Bool = True boundedType Natural = True boundedType Integer = True boundedType Double = True boundedType Text = True boundedType (App List _) = False boundedType (App Optional t) = boundedType t boundedType (Record kvs) = all boundedType kvs boundedType (Union kvs) = all boundedType kvs boundedType _ = False -- | Remove all `Note` constructors from an `Expr` (i.e. de-`Note`) denote :: Expr s a -> Expr t a denote (Note _ b ) = denote b denote (Const a ) = Const a denote (Var a ) = Var a denote (Lam a b c ) = Lam a (denote b) (denote c) denote (Pi a b c ) = Pi a (denote b) (denote c) denote (App a b ) = App (denote a) (denote b) denote (Let 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 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 denote a) denote (UnionLit a b c ) = UnionLit a (denote b) (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 (Constructors a ) = Constructors (denote a) denote (Field a b ) = Field (denote a) b denote (Project a b ) = Project (denote a) 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 => Normalizer a -> Expr s a -> Expr t a normalizeWith ctx = runIdentity . normalizeWithM ctx normalizeWithM :: (Eq a, Monad m) => 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 case f' of Lam x _A b -> loop b'' where a' = shift 1 (V x 0) a b' = subst (V x 0) a' b b'' = shift (-1) (V x 0) b' _ -> do a' <- loop a 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 n0 lazy = loop ( lazyLoop n0) 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) _ -> do res2 <- ctx (App f' a') case res2 of Nothing -> pure (App f' a') Just app' -> loop app' Let (Binding x _ a₀ :| ls₀) b₀ -> loop b₂ where rest = case ls₀ of [] -> b₀ l₁ : ls₁ -> Let (l₁ :| ls₁) b₀ a₁ = shift 1 (V x 0) a₀ b₁ = subst (V x 0) a₁ rest b₂ = shift (-1) (V x 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 | 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 -> decide <$> loop x <*> loop y where isEmpty (Chunks [] "") = True isEmpty _ = False decide (TextLit m) r | isEmpty m = r decide l (TextLit n) | isEmpty n = l decide (TextLit m) (TextLit n) = TextLit (m <> n) decide l r = TextAppend l r List -> 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 loop kts UnionLit k v kvs -> UnionLit k <$> v' <*> (Dhall.Map.sort <$> kvs') where v' = loop v kvs' = 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' _ -> Merge x' y' <$> t' _ -> Merge x' y' <$> t' where t' = traverse loop t Constructors t -> do t' <- loop t case t' of Union kts -> pure (RecordLit kvs) where kvs = Dhall.Map.mapWithKey adapt kts adapt k t_ = Lam k t_ (UnionLit k (Var (V k 0)) rest) where rest = Dhall.Map.delete k kts _ -> pure (Constructors 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 Union kvs -> case Dhall.Map.lookup x kvs of Just t_ -> Lam x <$> t' <*> pure (UnionLit x (Var (V x 0)) rest) where t' = loop t_ rest = Dhall.Map.delete x kvs Nothing -> Field <$> (Union <$> traverse loop kvs) <*> pure x _ -> pure (Field r' x) Project r 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 xs where adapt x = do v <- Dhall.Map.lookup x kvs return (x, v) _ -> pure (Project r' xs) Note _ e' -> loop e' ImportAlt l _r -> loop l Embed a -> pure (Embed a) {-| Returns `True` if two expressions are α-equivalent and β-equivalent and `False` otherwise -} judgmentallyEqual :: Eq a => Expr s a -> Expr t a -> Bool judgmentallyEqual eL0 eR0 = alphaBetaNormalize eL0 == alphaBetaNormalize eR0 where alphaBetaNormalize :: Eq a => Expr s a -> Expr () a alphaBetaNormalize = alphaNormalize . normalize -- | Use this to wrap you embedded functions (see `normalizeWith`) to make them -- polymorphic enough to be used. type 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. data 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 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 _ -> 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 x y -> loop x && loop y && decide x y where isEmpty (Chunks [] "") = True isEmpty _ = False decide (TextLit m) _ | isEmpty m = False decide _ (TextLit n) | isEmpty n = False decide (TextLit _) (TextLit _) = False decide _ _ = 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 loop kts UnionLit _ v kvs -> loop v && Dhall.Map.isSorted kvs && 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 Constructors t -> loop t && case t of Union _ -> False _ -> 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 -> if all (flip Dhall.Map.member kvs) xs then False else True _ -> True 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" , "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 a b)) = TextLit <$> (Chunks <$> traverse (traverse f) a <*> pure b) subExpressions f (TextAppend a b) = TextAppend <$> f a <*> f b 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 f a subExpressions f (UnionLit a b c) = UnionLit a <$> f b <*> 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 (Constructors a) = Constructors <$> f a 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) {-| 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 <> "\"" dhall-1.19.1/src/Dhall/Core.hs-boot0000644000000000000000000000007513377175666015104 0ustar0000000000000000module Dhall.Core where data Const data Var data Expr s a dhall-1.19.1/src/Dhall/Diff.hs0000644000000000000000000010624013377175666014124 0ustar0000000000000000{-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} {-| This module provides functionality for concisely displaying the difference between two expressions For example, this is used in type errors to explain why the actual type does not match the expected type -} module Dhall.Diff ( -- * Diff diffNormalized , Dhall.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.Map (Map) import Dhall.Set (Set) import Dhall.Pretty.Internal (Ann) import Numeric.Natural (Natural) 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 Dhall.Map import qualified Dhall.Set import qualified Dhall.Pretty.Internal as Internal data Diff = Diff { same :: Bool , doc :: Doc Ann } instance Data.Semigroup.Semigroup Diff where Diff sameL docL <> Diff sameR docR = Diff (sameL && sameR) (docL <> docR) instance Monoid (Diff) where mempty = Diff {..} where same = True doc = mempty #if !(MIN_VERSION_base(4,11,0)) mappend = (<>) #endif instance IsString (Diff) where fromString string = Diff {..} where same = True doc = fromString string ignore :: Diff ignore = "…" align :: Diff -> Diff align (Diff {doc = docOld, ..}) = Diff {doc = Pretty.align docOld, .. } hardline :: Diff hardline = token Pretty.hardline minus :: Diff -> Diff minus l = ("- " <> l) { same = False } plus :: Diff -> Diff plus r = ("+ " <> r) { same = False } difference :: Diff -> Diff -> Diff difference l r = align (minus l <> hardline <> plus r) token :: Doc Ann -> Diff token doc = Diff {..} where same = True format :: Diff -> Diff -> Diff format suffix doc = doc <> (if same doc then suffix else hardline) builtin :: Doc Ann -> Diff builtin doc = token (Internal.builtin doc) keyword :: Doc Ann -> Diff keyword doc = token (Internal.keyword doc) operator :: Doc Ann -> Diff operator doc = token (Internal.operator doc) colon :: Diff colon = token Internal.colon comma :: Diff comma = token Internal.comma dot :: Diff dot = token Internal.dot equals :: Diff equals = token Internal.equals forall :: Diff forall = token (Internal.forall Internal.Unicode) lambda :: Diff lambda = token (Internal.lambda Internal.Unicode) langle :: Diff langle = token Internal.langle lbrace :: Diff lbrace = token Internal.lbrace lbracket :: Diff lbracket = token Internal.lbracket lparen :: Diff lparen = token Internal.lparen pipe :: Diff pipe = token Internal.pipe rangle :: Diff rangle = token Internal.rangle rarrow :: Diff rarrow = token (Internal.rarrow Internal.Unicode) rbrace :: Diff rbrace = token Internal.rbrace rbracket :: Diff rbracket = token Internal.rbracket rparen :: Diff rparen = token Internal.rparen -- | Render the difference between the normal form of two expressions diffNormalized :: (Eq a, Pretty a) => Expr s a -> Expr s a -> Doc Ann 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 diffPrimitive :: Eq a => (a -> Diff) -> a -> a -> Diff diffPrimitive f l r | l == r = ignore | otherwise = difference (f l) (f r) diffLabel :: Text -> Text -> Diff diffLabel = diffPrimitive (token . Internal.prettyLabel) diffLabels :: Set Text -> Set 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 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))) diffNatural :: Natural -> Natural -> Diff diffNatural = diffPrimitive (token . Internal.prettyNatural) diffDouble :: Double -> Double -> Diff diffDouble = diffPrimitive (token . Internal.prettyDouble) diffConst :: Const -> Const -> Diff diffConst = diffPrimitive (token . Internal.prettyConst) diffBool :: Bool -> Bool -> Diff diffBool = diffPrimitive bool where bool True = builtin "True" bool False = builtin "False" diffInteger :: Integer -> Integer -> Diff diffInteger = diffPrimitive (token . Internal.prettyNumber) diffVar :: Var -> Var -> Diff diffVar (V xL nL) (V xR nR) = format mempty label <> "@" <> natural where label = diffLabel xL xR natural = diffInteger nL nR diffPretty :: (Eq a, Pretty a) => a -> a -> Diff diffPretty = diffPrimitive (token . Pretty.pretty) diffMaybe :: Diff -> (a -> a -> Diff) -> (Maybe a -> Maybe a -> Diff) diffMaybe _ _ Nothing Nothing = mempty diffMaybe prefix _ Nothing (Just _) = difference mempty (prefix <> ignore) diffMaybe prefix _ (Just _) Nothing = difference (prefix <> ignore) mempty diffMaybe prefix f (Just l) (Just r) = prefix <> f l r enclosed :: Diff -> Diff -> Diff -> [Diff] -> Diff enclosed l _ r [] = l <> r enclosed l m r docs = align (fold (zipWith (<>) prefixes docs) <> suffix) where prefixes = l : repeat (hardline <> m) suffix = hardline <> r enclosed' :: Diff -> Diff -> NonEmpty (Diff) -> Diff enclosed' l m docs = align (fold (Data.List.NonEmpty.zipWith (<>) prefixes docs)) where prefixes = l :| repeat (hardline <> m) diffKeyVals :: (Eq a, Pretty a) => Diff -> Map Text (Expr s a) -> Map Text (Expr s a) -> [Diff] diffKeyVals assign 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) extraL = Data.Set.difference ksL ksR extraR = Data.Set.difference ksR ksL diffFieldNames = foldMap (adapt minus) extraL <> foldMap (adapt plus) extraR where adapt sign key = [ sign (token (Internal.prettyLabel key)) <> " " <> assign <> " " <> ignore ] shared = Dhall.Map.intersectionWith diffExpression kvsL kvsR diffFieldValues = filter (not . same) (Dhall.Map.foldMapWithKey adapt shared) where adapt key doc = [ (if ksL == ksR then mempty else " ") <> token (Internal.prettyLabel key) <> " " <> assign <> " " <> doc ] anyEqual = getAny (foldMap (Any . same) shared) braced :: [Diff] -> Diff braced = enclosed (lbrace <> " ") (comma <> " ") rbrace angled :: [Diff] -> Diff angled = enclosed (langle <> " ") (pipe <> " ") rangle bracketed :: [Diff] -> Diff bracketed = enclosed (lbracket <> " ") (comma <> " ") rbracket diffText :: Text -> Text -> Diff diffText l r | null parts = "\"\"" | allDifferent parts = difference textSkeleton textSkeleton | allSame parts = textSkeleton | otherwise = "\"" <> foldMap prettyPart parts <> "\"" where allDifferent = not . any isBoth allSame = all isBoth -- TODO: check for color support from the TTY colorDiff colorCode chars = "\ESC[" <> colorCode <> "m" <> fromString chars <> "\ESC[0m" prettyPart part = case part of -- Only present in left Algo.Diff.First chars -> -- Red background (colorDiff "41" chars) { same = False } -- Only present in right Algo.Diff.Second chars -> -- Green background (colorDiff "42" chars) { same = False } -- Present in both Algo.Diff.Both _ chars -> -- Dim foreground colorDiff "2" chars parts = Algo.Diff.getGroupedDiff (Data.Text.unpack l) (Data.Text.unpack r) diffChunks :: (Eq a, Pretty a) => Chunks s a -> Chunks s a -> Diff diffChunks cL cR | null chunks = "\"\"" | [c] <- chunks = c | otherwise = align (enclosed " " "++ " "" chunks) where toEitherList (Chunks te t) = concatMap (\(a, b) -> [Left a, Right b]) te ++ [Left t] diffTextSkeleton = difference textSkeleton textSkeleton chunks = zipWith chunkDiff (toEitherList cL) (toEitherList cR) chunkDiff a b = case (a, b) of (Left x, Left y ) -> diffText x y (Right x, Right y) -> diffExpression x y _ -> diffTextSkeleton 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) where allDifferent = not . any 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) -- Render each element of a list using an extra rendering function f prettyElems f = map (f . token . Internal.prettyExpr) diffPart part = case part of -- Only present in left Algo.Diff.First elements -> prettyElems minus elements -- Only present in right Algo.Diff.Second elements -> prettyElems plus elements -- Present in both Algo.Diff.Both _ _ -> pure ignore -- 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 diffRecord kvsL kvsR = braced (diffKeyVals colon kvsL kvsR) diffRecordLit :: (Eq a, Pretty a) => Map Text (Expr s a) -> Map Text (Expr s a) -> Diff diffRecordLit kvsL kvsR = braced (diffKeyVals equals kvsL kvsR) diffUnion :: (Eq a, Pretty a) => Map Text (Expr s a) -> Map Text (Expr s a) -> Diff diffUnion kvsL kvsR = angled (diffKeyVals colon kvsL kvsR) diffUnionLit :: (Eq a, Pretty a) => Text -> Text -> Expr s a -> Expr s a -> Map Text (Expr s a) -> Map Text (Expr s a) -> Diff diffUnionLit kL kR vL vR kvsL kvsR = langle <> " " <> format " " (diffLabel kL kR) <> equals <> " " <> format " " (diffExpression vL vR) <> halfAngled (diffKeyVals equals kvsL kvsR) where halfAngled = enclosed (pipe <> " ") (pipe <> " ") rangle listSkeleton :: Diff listSkeleton = lbracket <> " " <> ignore <> " " <> rbracket textSkeleton :: Diff textSkeleton = "\"" <> ignore <> "\"" skeleton :: Pretty a => Expr s a -> Diff skeleton (Lam {}) = lambda <> lparen <> ignore <> " " <> colon <> " " <> ignore <> rparen <> " " <> rarrow <> " " <> ignore skeleton (Pi {}) = ignore <> " " <> rarrow <> " " <> ignore skeleton (App Optional _) = "Optional " <> ignore skeleton (App None _) = "None " <> ignore skeleton (Some _) = "Some " <> ignore skeleton (App List _) = "List " <> ignore skeleton (App {}) = ignore <> " " <> ignore skeleton (Let {}) = keyword "let" <> " " <> ignore <> " " <> equals <> " " <> ignore <> " " <> keyword "in" <> " " <> ignore skeleton (Annot {}) = ignore <> " " <> colon <> " " <> ignore skeleton (BoolAnd {}) = ignore <> " " <> operator "&&" <> " " <> ignore skeleton (BoolOr {}) = ignore <> " " <> operator "||" <> " " <> ignore skeleton (BoolEQ {}) = ignore <> " " <> operator "==" <> " " <> ignore skeleton (BoolNE {}) = ignore <> " " <> operator "!=" <> " " <> ignore skeleton (BoolIf {}) = keyword "if" <> " " <> ignore <> " " <> keyword "then" <> " " <> ignore <> " " <> keyword "else" <> " " <> ignore skeleton (NaturalPlus {}) = ignore <> " " <> operator "+" <> " " <> ignore skeleton (NaturalTimes {}) = ignore <> " " <> operator "*" <> " " <> ignore skeleton (TextLit {}) = textSkeleton skeleton (TextAppend {}) = ignore <> " " <> operator "++" <> " " <> ignore skeleton (ListLit {}) = listSkeleton <> " " <> colon <> " " <> builtin "List" <> " " <> ignore skeleton (ListAppend {}) = ignore <> " " <> operator "#" <> " " <> ignore skeleton (OptionalLit {}) = lbracket <> " " <> ignore <> " " <> rbracket <> " " <> colon <> " " <> builtin "Optional" <> " " <> ignore skeleton (Record {}) = lbrace <> " " <> ignore <> " " <> colon <> " " <> ignore <> " " <> rbrace skeleton (RecordLit {}) = lbrace <> " " <> ignore <> " " <> equals <> " " <> ignore <> " " <> rbrace skeleton (Union {}) = langle <> " " <> ignore <> " " <> colon <> " " <> ignore <> " " <> rangle skeleton (UnionLit {}) = langle <> " " <> ignore <> " " <> equals <> " " <> ignore <> " " <> rangle skeleton (Combine {}) = ignore <> " " <> operator "∧" <> " " <> ignore skeleton (CombineTypes {}) = ignore <> " " <> operator "⩓" <> " " <> ignore skeleton (Prefer {}) = ignore <> " " <> operator "⫽" <> " " <> ignore skeleton (Merge {}) = keyword "merge" <> " " <> ignore <> " " <> ignore skeleton (Constructors {}) = keyword "constructors" <> " " <> ignore skeleton (Field {}) = ignore <> dot <> ignore skeleton (Project {}) = ignore <> dot <> lbrace <> " " <> ignore <> " " <> rbrace 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 {}) = enclosed' " " (rarrow <> " ") (docs l r) where docs (Lam aL bL cL) (Lam aR bR cR) = Data.List.NonEmpty.cons (align doc) (docs cL cR) where doc = lambda <> lparen <> format " " (diffLabel aL aR) <> colon <> " " <> format mempty (diffExpression bL bR) <> rparen docs aL aR = pure (diffExpression aL aR) diffExpression l@(Lam {}) r = mismatch l r diffExpression l r@(Lam {}) = mismatch l r diffExpression l@(BoolIf {}) r@(BoolIf {}) = enclosed' " " (keyword "else" <> " ") (docs l r) where docs (BoolIf aL bL cL) (BoolIf aR bR cR) = Data.List.NonEmpty.cons (align doc) (docs cL cR) where doc = keyword "if" <> " " <> format " " (diffExpression aL aR) <> keyword "then" <> " " <> diffExpression bL bR docs aL aR = pure (diffExpression aL aR) diffExpression l@(BoolIf {}) r = mismatch l r diffExpression 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) where docA (Binding cL dL eL) (Binding cR dR eR) = align doc where doc = keyword "let" <> " " <> format " " (diffLabel cL cR) <> format " " (diffMaybe (colon <> " ") diffExpression dL dR) <> equals <> " " <> diffExpression eL eR docB = diffExpression bL bR diffExpression l@(Let {}) r = mismatch l r diffExpression l r@(Let {}) = mismatch l r diffExpression l@(Pi {}) r@(Pi {}) = enclosed' " " (rarrow <> " ") (docs l r) where docs (Pi aL bL cL) (Pi aR bR cR) = Data.List.NonEmpty.cons (align doc) (docs cL cR) where doc | same docA && same docB = ignore | otherwise = forall <> lparen <> format " " docA <> colon <> " " <> format mempty docB <> rparen where docA = diffLabel aL aR docB = diffExpression bL bR docs aL aR = pure (diffExpression aL aR) diffExpression l@(Pi {}) r = mismatch l r diffExpression l r@(Pi {}) = mismatch l r diffExpression l r = diffAnnotatedExpression l r diffAnnotatedExpression :: (Eq a, Pretty a) => Expr s a -> Expr s 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) <> diffMaybe (colon <> " ") diffApplicationExpression cL cR diffAnnotatedExpression l@(Merge {}) r = mismatch l r diffAnnotatedExpression l r@(Merge {}) = 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) 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 diffAnnotatedExpression l@(Annot {}) r@(Annot {}) = enclosed' " " (colon <> " ") (docs l r) where docs (Annot aL bL) (Annot aR bR) = Data.List.NonEmpty.cons (align doc) (docs bL bR) where doc = diffOperatorExpression aL aR docs aL aR = diffExpression aL aR :| [] diffAnnotatedExpression l@(Annot {}) r = mismatch l r diffAnnotatedExpression l r@(Annot {}) = mismatch l r diffAnnotatedExpression l r = diffOperatorExpression l r diffOperatorExpression :: (Eq a, Pretty a) => Expr s a -> Expr s a -> Diff diffOperatorExpression = diffOrExpression diffOrExpression :: (Eq a, Pretty a) => Expr s a -> Expr s 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) docs aL aR = pure (diffTextAppendExpression aL aR) diffOrExpression l@(BoolOr {}) r = mismatch l r diffOrExpression l r@(BoolOr {}) = mismatch l r diffOrExpression l r = diffPlusExpression l r diffPlusExpression :: (Eq a, Pretty a) => Expr s a -> Expr s 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) docs aL aR = pure (diffListAppendExpression aL aR) diffPlusExpression l@(NaturalPlus {}) r = mismatch l r diffPlusExpression l r@(NaturalPlus {}) = mismatch l r diffPlusExpression l r = diffTextAppendExpression l r diffTextAppendExpression :: (Eq a, Pretty a) => Expr s a -> Expr s 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) docs aL aR = pure (diffPlusExpression aL aR) diffTextAppendExpression l@(TextAppend {}) r = mismatch l r diffTextAppendExpression l r@(TextAppend {}) = mismatch l r diffTextAppendExpression l r = diffListAppendExpression l r diffListAppendExpression :: (Eq a, Pretty a) => Expr s a -> Expr s a -> Diff diffListAppendExpression l@(ListAppend {}) r@(ListAppend {}) = enclosed' " " (operator "#" <> " ") (docs l r) where docs (ListAppend aL bL) (ListAppend aR bR) = Data.List.NonEmpty.cons (diffAndExpression aL aR) (docs bL bR) docs aL aR = pure (diffAndExpression aL aR) diffListAppendExpression l@(ListAppend {}) r = mismatch l r diffListAppendExpression l r@(ListAppend {}) = mismatch l r diffListAppendExpression l r = diffAndExpression l r diffAndExpression :: (Eq a, Pretty a) => Expr s a -> Expr s a -> Diff diffAndExpression l@(BoolAnd {}) r@(BoolAnd {}) = enclosed' " " (operator "&&" <> " ") (docs l r) where docs (BoolAnd aL bL) (BoolAnd aR bR) = Data.List.NonEmpty.cons (diffCombineExpression aL aR) (docs bL bR) docs aL aR = pure (diffCombineExpression aL aR) diffAndExpression l@(BoolAnd {}) r = mismatch l r diffAndExpression l r@(BoolAnd {}) = mismatch l r diffAndExpression l r = diffCombineExpression l r diffCombineExpression :: (Eq a, Pretty a) => Expr s a -> Expr s a -> Diff diffCombineExpression l@(Combine {}) r@(Combine {}) = enclosed' " " (operator "∧" <> " ") (docs l r) where docs (Combine aL bL) (Combine aR bR) = Data.List.NonEmpty.cons (diffPreferExpression aL aR) (docs bL bR) docs aL aR = pure (diffPreferExpression aL aR) diffCombineExpression l@(Combine {}) r = mismatch l r diffCombineExpression l r@(Combine {}) = mismatch l r diffCombineExpression l r = diffPreferExpression l r diffPreferExpression :: (Eq a, Pretty a) => Expr s a -> Expr s a -> Diff diffPreferExpression l@(Prefer {}) r@(Prefer {}) = enclosed' " " (operator "⫽" <> " ") (docs l r) where docs (Prefer aL bL) (Prefer aR bR) = Data.List.NonEmpty.cons (diffCombineTypesExpression aL aR) (docs bL bR) docs aL aR = pure (diffCombineTypesExpression aL aR) diffPreferExpression l@(Prefer {}) r = mismatch l r diffPreferExpression l r@(Prefer {}) = mismatch l r diffPreferExpression l r = diffCombineTypesExpression l r diffCombineTypesExpression :: (Eq a, Pretty a) => Expr s a -> Expr s a -> Diff diffCombineTypesExpression l@(CombineTypes {}) r@(CombineTypes {}) = enclosed' " " (operator "*" <> " ") (docs l r) where docs (CombineTypes aL bL) (CombineTypes aR bR) = Data.List.NonEmpty.cons (diffTimesExpression aL aR) (docs bL bR) docs aL aR = pure (diffTimesExpression aL aR) diffCombineTypesExpression l@(CombineTypes {}) r = mismatch l r diffCombineTypesExpression l r@(CombineTypes {}) = mismatch l r diffCombineTypesExpression l r = diffTimesExpression l r diffTimesExpression :: (Eq a, Pretty a) => Expr s a -> Expr s a -> Diff diffTimesExpression l@(NaturalTimes {}) r@(NaturalTimes {}) = enclosed' " " (operator "*" <> " ") (docs l r) where docs (NaturalTimes aL bL) (NaturalTimes aR bR) = Data.List.NonEmpty.cons (diffEqualExpression aL aR) (docs bL bR) docs aL aR = pure (diffEqualExpression aL aR) diffTimesExpression l@(NaturalTimes {}) r = mismatch l r diffTimesExpression l r@(NaturalTimes {}) = mismatch l r diffTimesExpression l r = diffEqualExpression l r diffEqualExpression :: (Eq a, Pretty a) => Expr s a -> Expr s a -> Diff diffEqualExpression l@(BoolEQ {}) r@(BoolEQ {}) = enclosed' " " (operator "==" <> " ") (docs l r) where docs (BoolEQ aL bL) (BoolEQ aR bR) = Data.List.NonEmpty.cons (diffNotEqualExpression aL aR) (docs bL bR) docs aL aR = pure (diffNotEqualExpression aL aR) diffEqualExpression l@(BoolEQ {}) r = mismatch l r diffEqualExpression l r@(BoolEQ {}) = mismatch l r diffEqualExpression l r = diffNotEqualExpression l r diffNotEqualExpression :: (Eq a, Pretty a) => Expr s a -> Expr s 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) docs aL aR = pure (diffApplicationExpression aL aR) diffNotEqualExpression l@(BoolNE {}) r = mismatch l r diffNotEqualExpression l r@(BoolNE {}) = mismatch l r diffNotEqualExpression l r = diffApplicationExpression l r diffApplicationExpression :: (Eq a, Pretty a) => Expr s a -> Expr s 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) docs (Constructors aL) (Constructors aR) = diffImportExpression aL aR :| [ keyword "constructors" ] docs aL aR@(Constructors {}) = pure (mismatch aL aR) docs aL@(Constructors {}) aR = pure (mismatch aL aR) docs (Some aL) (Some aR) = diffImportExpression 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) diffApplicationExpression l@(App {}) r = mismatch l r diffApplicationExpression l r@(App {}) = mismatch l r diffApplicationExpression (Constructors l) (Constructors r) = enclosed' mempty mempty (keyword "constructors" :| [ diffImportExpression l r ]) diffApplicationExpression l@(Constructors {}) r = mismatch l r diffApplicationExpression l r@(Constructors {}) = mismatch l r diffApplicationExpression (Some l) (Some r) = enclosed' mempty mempty (builtin "Some" :| [ diffImportExpression l r ]) diffApplicationExpression l@(Some {}) r = mismatch l r diffApplicationExpression l r@(Some {}) = mismatch l r diffApplicationExpression l r = diffImportExpression l r diffImportExpression :: (Eq a, Pretty a) => Expr s a -> Expr s a -> Diff diffImportExpression (Embed l) (Embed r) = diffPretty l r diffImportExpression l@(Embed {}) r = mismatch l r diffImportExpression l r@(Embed {}) = mismatch l r diffImportExpression l r = diffSelectorExpression l r diffSelectorExpression :: (Eq a, Pretty a) => Expr s a -> Expr s a -> Diff diffSelectorExpression l@(Field {}) r@(Field {}) = enclosed' " " (dot <> " ") (Data.List.NonEmpty.reverse (docs l r)) where docs (Field aL bL) (Field aR bR) = Data.List.NonEmpty.cons (diffLabel bL bR) (docs aL aR) docs (Project aL bL) (Project aR bR) = Data.List.NonEmpty.cons (diffLabels bL bR) (docs aL aR) docs aL aR = pure (diffPrimitiveExpression aL aR) diffSelectorExpression l@(Field {}) r = mismatch l r diffSelectorExpression l r@(Field {}) = mismatch l r diffSelectorExpression l@(Project {}) r@(Project {}) = enclosed' " " (dot <> " ") (Data.List.NonEmpty.reverse (docs l r)) where docs (Field aL bL) (Field aR bR) = Data.List.NonEmpty.cons (diffLabel bL bR) (docs aL aR) docs (Project aL bL) (Project aR bR) = Data.List.NonEmpty.cons (diffLabels bL bR) (docs aL aR) docs aL aR = pure (diffPrimitiveExpression aL aR) diffSelectorExpression l@(Project {}) r = mismatch l r diffSelectorExpression l r@(Project {}) = mismatch l r diffSelectorExpression l r = diffPrimitiveExpression l r diffPrimitiveExpression :: (Eq a, Pretty a) => Expr s a -> Expr s a -> Diff diffPrimitiveExpression (Var aL) (Var aR) = diffVar aL aR diffPrimitiveExpression l@(Var {}) r = mismatch l r diffPrimitiveExpression l r@(Var {}) = mismatch l r diffPrimitiveExpression (Const aL) (Const aR) = diffConst aL aR diffPrimitiveExpression l@(Const {}) r = mismatch l r diffPrimitiveExpression l r@(Const {}) = mismatch l r diffPrimitiveExpression Bool Bool = "…" diffPrimitiveExpression l@Bool r = mismatch l r diffPrimitiveExpression l r@Bool = mismatch l r diffPrimitiveExpression Natural Natural = "…" diffPrimitiveExpression l@Natural r = mismatch l r diffPrimitiveExpression l r@Natural = mismatch l r diffPrimitiveExpression NaturalFold NaturalFold = "…" diffPrimitiveExpression l@NaturalFold r = mismatch l r diffPrimitiveExpression l r@NaturalFold = mismatch l r diffPrimitiveExpression NaturalBuild NaturalBuild = "…" diffPrimitiveExpression l@NaturalBuild r = mismatch l r diffPrimitiveExpression l r@NaturalBuild = mismatch l r diffPrimitiveExpression NaturalIsZero NaturalIsZero = "…" diffPrimitiveExpression l@NaturalIsZero r = mismatch l r diffPrimitiveExpression l r@NaturalIsZero = mismatch l r diffPrimitiveExpression NaturalEven NaturalEven = "…" diffPrimitiveExpression l@NaturalEven r = mismatch l r diffPrimitiveExpression l r@NaturalEven = mismatch l r diffPrimitiveExpression NaturalOdd NaturalOdd = "…" diffPrimitiveExpression l@NaturalOdd r = mismatch l r diffPrimitiveExpression l r@NaturalOdd = mismatch l r diffPrimitiveExpression NaturalToInteger NaturalToInteger = "…" diffPrimitiveExpression l@NaturalToInteger r = mismatch l r diffPrimitiveExpression l r@NaturalToInteger = mismatch l r diffPrimitiveExpression NaturalShow NaturalShow = "…" diffPrimitiveExpression l@NaturalShow r = mismatch l r diffPrimitiveExpression l r@NaturalShow = mismatch l r diffPrimitiveExpression Integer Integer = "…" diffPrimitiveExpression l@Integer r = mismatch l r diffPrimitiveExpression l r@Integer = mismatch l r diffPrimitiveExpression IntegerShow IntegerShow = "…" diffPrimitiveExpression l@IntegerShow r = mismatch l r diffPrimitiveExpression l r@IntegerShow = mismatch l r diffPrimitiveExpression IntegerToDouble IntegerToDouble = "…" diffPrimitiveExpression l@IntegerToDouble r = mismatch l r diffPrimitiveExpression l r@IntegerToDouble = mismatch l r diffPrimitiveExpression Double Double = "…" diffPrimitiveExpression l@Double r = mismatch l r diffPrimitiveExpression l r@Double = mismatch l r diffPrimitiveExpression DoubleShow DoubleShow = "…" diffPrimitiveExpression l@DoubleShow r = mismatch l r diffPrimitiveExpression l r@DoubleShow = mismatch l r diffPrimitiveExpression Text Text = "…" diffPrimitiveExpression l@Text r = mismatch l r diffPrimitiveExpression l r@Text = mismatch l r diffPrimitiveExpression List List = "…" diffPrimitiveExpression l@List r = mismatch l r diffPrimitiveExpression l r@List = mismatch l r diffPrimitiveExpression (ListLit Nothing bL) (ListLit Nothing bR) = align doc where doc = format " " (diffList bL bR) diffPrimitiveExpression l@(ListLit {}) r = mismatch l r diffPrimitiveExpression l r@(ListLit {}) = mismatch l r diffPrimitiveExpression ListBuild ListBuild = "…" diffPrimitiveExpression l@ListBuild r = mismatch l r diffPrimitiveExpression l r@ListBuild = mismatch l r diffPrimitiveExpression ListFold ListFold = "…" diffPrimitiveExpression l@ListFold r = mismatch l r diffPrimitiveExpression l r@ListFold = mismatch l r diffPrimitiveExpression ListLength ListLength = "…" diffPrimitiveExpression l@ListLength r = mismatch l r diffPrimitiveExpression l r@ListLength = mismatch l r diffPrimitiveExpression ListHead ListHead = "…" diffPrimitiveExpression l@ListHead r = mismatch l r diffPrimitiveExpression l r@ListHead = mismatch l r diffPrimitiveExpression ListLast ListLast = "…" diffPrimitiveExpression l@ListLast r = mismatch l r diffPrimitiveExpression l r@ListLast = mismatch l r diffPrimitiveExpression ListIndexed ListIndexed = "…" diffPrimitiveExpression l@ListIndexed r = mismatch l r diffPrimitiveExpression l r@ListIndexed = mismatch l r diffPrimitiveExpression ListReverse ListReverse = "…" diffPrimitiveExpression l@ListReverse r = mismatch l r diffPrimitiveExpression l r@ListReverse = mismatch l r diffPrimitiveExpression Optional Optional = "…" diffPrimitiveExpression l@Optional r = mismatch l r diffPrimitiveExpression l r@Optional = mismatch l r diffPrimitiveExpression None None = "…" diffPrimitiveExpression l@None r = mismatch l r diffPrimitiveExpression l r@None = mismatch l r diffPrimitiveExpression 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 = mismatch l r diffPrimitiveExpression l r@(BoolLit {}) = mismatch l r diffPrimitiveExpression (IntegerLit aL) (IntegerLit aR) = diffInteger aL aR diffPrimitiveExpression l@(IntegerLit {}) r = mismatch l r diffPrimitiveExpression l r@(IntegerLit {}) = mismatch l r diffPrimitiveExpression (NaturalLit aL) (NaturalLit aR) = diffNatural aL aR diffPrimitiveExpression l@(NaturalLit {}) r = mismatch l r diffPrimitiveExpression l r@(NaturalLit {}) = mismatch l r diffPrimitiveExpression (DoubleLit aL) (DoubleLit aR) = diffDouble aL aR diffPrimitiveExpression l@(DoubleLit {}) r = mismatch l r diffPrimitiveExpression l r@(DoubleLit {}) = mismatch l r diffPrimitiveExpression (TextLit l) (TextLit r) = diffChunks l r diffPrimitiveExpression l@(TextLit {}) r = mismatch l r diffPrimitiveExpression l r@(TextLit {}) = mismatch l r diffPrimitiveExpression (Record aL) (Record aR) = diffRecord aL aR diffPrimitiveExpression l@(Record {}) r = mismatch l r diffPrimitiveExpression l r@(Record {}) = mismatch l r diffPrimitiveExpression (RecordLit aL) (RecordLit aR) = diffRecordLit aL aR diffPrimitiveExpression l@(RecordLit {}) r = mismatch l r diffPrimitiveExpression l r@(RecordLit {}) = mismatch l r diffPrimitiveExpression (Union aL) (Union aR) = diffUnion aL aR diffPrimitiveExpression l@(Union {}) r = mismatch l r diffPrimitiveExpression l r@(Union {}) = mismatch l r diffPrimitiveExpression (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 dhall-1.19.1/src/Dhall/Format.hs0000644000000000000000000000450413377175666014504 0ustar0000000000000000{-# LANGUAGE OverloadedStrings #-} -- | This module contains the implementation of the @dhall format@ subcommand module Dhall.Format ( -- * Format format ) where import Dhall.Parser (exprAndHeaderFromText) import Dhall.Pretty (CharacterSet(..), annToAnsiStyle, layoutOpts) import Data.Monoid ((<>)) import qualified Data.Text.Prettyprint.Doc as Pretty import qualified Data.Text.Prettyprint.Doc.Render.Terminal as Pretty import qualified Control.Exception import qualified Data.Text.IO import qualified Dhall.Pretty import qualified System.Console.ANSI import qualified System.IO -- | Implementation of the @dhall format@ subcommand format :: CharacterSet -> Maybe FilePath -- ^ Modify file in-place if present, otherwise read from @stdin@ and write -- to @stdout@ -> IO () format characterSet inplace = do case inplace of Just file -> do text <- Data.Text.IO.readFile file (header, expr) <- case exprAndHeaderFromText "(stdin)" text of Left err -> Control.Exception.throwIO err Right x -> return x let doc = Pretty.pretty header <> Pretty.unAnnotate (Dhall.Pretty.prettyCharacterSet characterSet expr) System.IO.withFile file System.IO.WriteMode (\handle -> do Pretty.renderIO handle (Pretty.layoutSmart layoutOpts doc) Data.Text.IO.hPutStrLn handle "" ) Nothing -> do inText <- Data.Text.IO.getContents (header, expr) <- case exprAndHeaderFromText "(stdin)" inText of Left err -> Control.Exception.throwIO err Right x -> return x let doc = Pretty.pretty header <> Dhall.Pretty.prettyCharacterSet characterSet expr supportsANSI <- System.Console.ANSI.hSupportsANSI System.IO.stdout if supportsANSI then Pretty.renderIO System.IO.stdout (fmap annToAnsiStyle (Pretty.layoutSmart layoutOpts doc)) else Pretty.renderIO System.IO.stdout (Pretty.layoutSmart layoutOpts (Pretty.unAnnotate doc)) dhall-1.19.1/src/Dhall/Freeze.hs0000644000000000000000000001050313377175666014470 0ustar0000000000000000{-# LANGUAGE OverloadedStrings #-} -- | This module contains the implementation of the @dhall freeze@ subcommand module Dhall.Freeze ( -- * Freeze freeze , hashImport ) 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(..)) import Dhall.Import (standardVersion) import Dhall.Parser (exprAndHeaderFromText, Src) import Dhall.Pretty (annToAnsiStyle, layoutOpts) import Dhall.TypeCheck (X) import Lens.Family (set) 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 Dhall.Import import qualified Dhall.TypeCheck import qualified System.FilePath import qualified System.IO -- | Retrieve an `Import` and update the hash to match the latest contents hashImport :: FilePath -- ^ Current working directory -> StandardVersion -> Import -> IO Import hashImport directory _standardVersion import_ = do let unprotectedImport = import_ { importHashed = (importHashed import_) { hash = Nothing } } 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 expression <- Control.Exception.handle handler download case Dhall.TypeCheck.typeOf expression of Left exception -> Control.Exception.throwIO exception Right _ -> return () let normalizedExpression = Dhall.Core.alphaNormalize (Dhall.Core.normalize expression) let expressionHash = Just (Dhall.Import.hashExpression _standardVersion normalizedExpression) let newImportHashed = (importHashed import_) { hash = expressionHash } let newImport = import_ { importHashed = newImportHashed } State.evalStateT (Dhall.Import.exprToImport newImport normalizedExpression) status return newImport parseExpr :: String -> Text -> IO (Text, Expr Src Import) parseExpr src txt = case exprAndHeaderFromText src txt of Left err -> Control.Exception.throwIO err Right x -> return x writeExpr :: Maybe FilePath -> (Text, Expr s Import) -> IO () writeExpr inplace (header, expr) = do let doc = Pretty.pretty header <> Pretty.pretty expr let stream = Pretty.layoutSmart layoutOpts doc case inplace of Just f -> System.IO.withFile f System.IO.WriteMode (\handle -> do Pretty.renderIO handle (annToAnsiStyle <$> stream) Data.Text.IO.hPutStrLn handle "" ) 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 (Pretty.layoutSmart layoutOpts (Pretty.unAnnotate doc)) -- | Implementation of the @dhall freeze@ subcommand freeze :: Maybe FilePath -- ^ Modify file in-place if present, otherwise read from @stdin@ and write -- to @stdout@ -> StandardVersion -> IO () freeze inplace _standardVersion = do (text, directory) <- case inplace of Nothing -> do text <- Data.Text.IO.getContents return (text, ".") Just file -> do text <- Data.Text.IO.readFile file return (text, System.FilePath.takeDirectory file) (header, parsedExpression) <- parseExpr srcInfo text frozenExpression <- traverse (hashImport directory _standardVersion) parsedExpression writeExpr inplace (header, frozenExpression) where srcInfo = fromMaybe "(stdin)" inplace dhall-1.19.1/src/Dhall/Hash.hs0000644000000000000000000000264013377175666014136 0ustar0000000000000000{-# 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) dhall-1.19.1/src/Dhall/Import.hs0000644000000000000000000010402613377175666014526 0ustar0000000000000000{-# 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 > > 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 > > "\n\n\n Example Domain\n\n charset=\"utf-8\" />\n ; charset=utf-8\" />\n initial-scale=1\" />\n \n\n\n\n
\n

Example Domain h1>\n

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.

\n

e\">More information...

\n

\n\n\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(..) ) 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 (sconcat, (<>)) 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(..) , ReifiedNormalizer(..) , Scheme(..) , 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(..)) 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 Network.URI.Encode 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 imports 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 (canonicalizeAll imports) -- 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 <> "\n" -- | Exception thrown when an environment variable is missing newtype MissingEnvironmentVariable = MissingEnvironmentVariable { name :: Text } deriving (Typeable) instance Exception MissingEnvironmentVariable instance Show MissingEnvironmentVariable where show (MissingEnvironmentVariable {..}) = "\n" <> "\ESC[1;31mError\ESC[0m: Missing environment variable\n" <> "\n" <> "↳ " <> Text.unpack name -- | 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" <> "\n" 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 <> "\n" 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" canonicalizeAll :: NonEmpty Import -> NonEmpty Import canonicalizeAll = NonEmpty.scanr1 step where step a parent = canonicalizeImport (a :| [parent]) {-| > canonicalize (canonicalize x) = canonicalize x -} class 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 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 canonicalizeImport :: NonEmpty Import -> Import canonicalizeImport imports = canonicalize (sconcat (NonEmpty.reverse imports)) 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 "/" 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 (Expr Src Import) exprFromImport here@(Import {..}) = do let ImportHashed {..} = importHashed 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 liftIO (Control.Exception.throwIO (HashMismatch {..})) let bytesLazy = Data.ByteString.Lazy.fromStrict bytesStrict term <- throws (Codec.Serialise.deserialiseOrFail bytesLazy) throws (Dhall.Binary.decodeWithVersion term) case result of Just expression -> return expression Nothing -> 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 _ <- throws (Dhall.TypeCheck.typeWith _startingContext expression) let normalizedExpression = Dhall.Core.alphaNormalize (Dhall.Core.normalizeWith (getReifiedNormalizer _normalizer) expression ) let bytes = encodeExpression _standardVersion normalizedExpression let actualHash = Crypto.Hash.hash bytes if expectedHash == actualHash then return () else liftIO (Control.Exception.throwIO (HashMismatch {..})) liftIO (Data.ByteString.writeFile cacheFile bytes) 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 assertDirectory cacheDirectory let dhallDirectory = cacheDirectory "dhall" assertDirectory dhallDirectory let cacheFile = dhallDirectory show hash return cacheFile getCacheDirectory :: MonadIO io => io FilePath #if MIN_VERSION_directory(1,2,3) getCacheDirectory = liftIO (Directory.getXdgDirectory Directory.XdgCache "") #else getCacheDirectory = liftIO $ do maybeXDGCacheHome <- System.Environment.lookupEnv "XDG_CACHE_HOME" case maybeXDGCacheHome of Nothing -> do homeDirectory <- Directory.getHomeDirectory return (homeDirectory ".cache") Just xdgCacheHome -> do return xdgCacheHome #endif exprFromUncachedImport :: Import -> StateT (Status IO) IO (Expr Src Import) exprFromUncachedImport (Import {..}) = do let ImportHashed {..} = importHashed (path, text) <- 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) Remote (URL scheme authority path query fragment maybeHeaders) -> do let prefix = (case scheme of HTTP -> "http"; HTTPS -> "https") <> "://" <> authority let File {..} = path let Directory {..} = directory let pathComponentToText component = "/" <> Network.URI.Encode.encodeText component let fileText = Text.concat (map pathComponentToText (reverse components)) <> pathComponentToText file let suffix = (case query of Nothing -> ""; Just q -> "?" <> q) <> (case fragment of Nothing -> ""; Just f -> "#" <> f) let url = Text.unpack (prefix <> fileText <> suffix) mheaders <- case maybeHeaders of Nothing -> return Nothing Just importHashed_ -> do expr <- loadWith (Embed (Import importHashed_ Code)) 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) Nothing -> do liftIO (throwIO InternalError) #ifdef MIN_VERSION_http_client fetchFromHttpUrl url mheaders #else liftIO (throwIO (CannotImportHTTPURL url mheaders)) #endif Env env -> liftIO $ do x <- System.Environment.lookupEnv (Text.unpack env) case x of Just string -> return (Text.unpack env, Text.pack string) Nothing -> 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 expr -> do return expr RawText -> do return (TextLit (Chunks [] text)) -- | 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 imports = _stack let local (Import (ImportHashed _ (Remote {})) _) = False local (Import (ImportHashed _ (Local {})) _) = True local (Import (ImportHashed _ (Env {})) _) = True local (Import (ImportHashed _ (Missing {})) _) = True let parent = canonicalizeImport imports let imports' = NonEmpty.cons import_ imports let here = canonicalizeImport imports' if local here && not (local parent) then throwMissingImport (Imported imports (ReferentiallyOpaque import_)) else return () expr <- if here `elem` canonicalizeAll imports then throwMissingImport (Imported imports (Cycle import_)) else do case Map.lookup here _cache of Just (hereNode, expr) -> do zoom dot . State.modify $ \getDot -> do parentNode <- getDot -- Add edge between parent and here parentNode .->. hereNode -- 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 (Expr Src Import) handler₀ (MissingImports es) = throwM (MissingImports (map (\e -> toException (Imported imports' e)) es ) ) handler₁ :: (MonadCatch m) => SomeException -> StateT (Status m) m (Expr Src Import) handler₁ e = throwMissingImport (Imported imports' e) -- This loads a \"dynamic\" expression (i.e. an expression -- that might still contain imports) let loadDynamic = _resolver here expr' <- loadDynamic `catches` [ Handler handler₀, Handler handler₁ ] let hereNodeId = userNodeId _nextNodeId -- Increment the next node id zoom nextNodeId $ State.modify succ -- Make current node the dot graph zoom dot . State.put $ importNode hereNodeId here zoom stack (State.put imports') expr'' <- loadWith expr' zoom stack (State.put imports) zoom dot . State.modify $ \getSubDot -> do parentNode <- _dot -- Get current node back from sub-graph hereNode <- getSubDot -- Add edge between parent and here parentNode .->. hereNode -- Return parent NodeId pure parentNode _cacher here 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 imports' err) Right _ -> return (Dhall.Core.normalizeWith (getReifiedNormalizer _normalizer) expr'') zoom cache (State.modify' (Map.insert here (hereNodeId, expr'''))) return expr''' case hash (importHashed import_) of Nothing -> do return () Just expectedHash -> do let actualHash = hashExpression _standardVersion (Dhall.Core.alphaNormalize expr) if expectedHash == actualHash then return () else throwMissingImport (Imported imports' (HashMismatch {..})) return expr ImportAlt a b -> loadWith a `catch` handler₀ where handler₀ (MissingImports es₀) = loadWith b `catch` handler₁ where handler₁ (MissingImports es₁) = throwM (MissingImports (es₀ ++ es₁)) 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 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 loadWith a UnionLit a b c -> UnionLit <$> pure a <*> loadWith b <*> 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 Constructors a -> Constructors <$> loadWith a Field a b -> Field <$> loadWith a <*> pure b Project a b -> Project <$> loadWith a <*> pure b Note a b -> Note <$> pure a <*> loadWith b -- | 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 -> Expr s X -> Data.ByteString.ByteString encodeExpression _standardVersion expression = bytesStrict where intermediateExpression :: Expr s Import intermediateExpression = fmap absurd expression term :: Term term = Dhall.Binary.encodeWithVersion _standardVersion intermediateExpression bytesLazy = Codec.Serialise.serialise term 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 = throws (traverse (\_ -> Left ImportResolutionDisabled) expression) throws :: (Exception e, MonadIO io) => Either e a -> io a throws (Left e) = liftIO (Control.Exception.throwIO e) throws (Right a) = return a dhall-1.19.1/src/Dhall/Lint.hs0000644000000000000000000001277413377175666014172 0ustar0000000000000000-- | This module contains the implementation of the @dhall lint@ command module Dhall.Lint ( -- * Lint lint ) where import Dhall.Core (Binding(..), Chunks(..), Expr(..), Import, Var(..)) import Data.Semigroup ((<>)) import Data.List.NonEmpty (NonEmpty(..)) import Dhall.TypeCheck (X(..)) import qualified Dhall.Core {-| Automatically improve a Dhall expression Currently this: * removes unused @let@ bindings * consolidates nested @let@ bindings to use a multiple-@let@ binding * switches legacy @List@-like @Optional@ literals to use @Some@ / @None@ instead -} lint :: Expr s Import -> Expr t Import lint expression = loop (Dhall.Core.denote expression) where loop (Const a) = Const a loop (Var a) = Var a loop (Lam a b c) = Lam a b' c' where b' = loop b c' = loop c loop (Pi a b c) = Pi a b' c' where b' = loop b c' = loop c loop (App a b) = App a' b' where a' = loop a b' = loop b -- Consolidate nested `let` expresssions loop (Let a (Let b c)) = loop (Let (a <> b) c) -- Remove unused bindings loop (Let (Binding a b c :| []) d) | not (V a 0 `Dhall.Core.freeIn` d') = d' | otherwise = Let (Binding a b' c' :| []) d' where b' = fmap loop b c' = loop c d' = loop d loop (Let (Binding a b c :| (l : ls)) d) | not (V a 0 `Dhall.Core.freeIn` Let (l' :| ls') d') = Let (l' :| ls') d' | otherwise = Let (Binding a b' c' :| (l' : ls')) d' where b' = fmap loop b c' = loop c Let (l' :| ls') d' = loop (Let (l :| ls) d) loop (Annot a b) = Annot a' b' where a' = loop a b' = loop b loop Bool = Bool loop (BoolLit a) = BoolLit a loop (BoolAnd a b) = BoolAnd a' b' where a' = loop a b' = loop b loop (BoolOr a b) = BoolOr a' b' where a' = loop a b' = loop b loop (BoolEQ a b) = BoolEQ a' b' where a' = loop a b' = loop b loop (BoolNE a b) = BoolNE a' b' where a' = loop a b' = loop b loop (BoolIf a b c) = BoolIf a' b' c' where a' = loop a b' = loop b c' = loop c loop Natural = Natural loop (NaturalLit a) = NaturalLit a loop NaturalFold = NaturalFold loop NaturalBuild = NaturalBuild loop NaturalIsZero = NaturalIsZero loop NaturalEven = NaturalEven loop NaturalOdd = NaturalOdd loop NaturalToInteger = NaturalToInteger loop NaturalShow = NaturalShow loop (NaturalPlus a b) = NaturalPlus a' b' where a' = loop a b' = loop b loop (NaturalTimes a b) = NaturalTimes a' b' where a' = loop a b' = loop b loop Integer = Integer loop (IntegerLit a) = IntegerLit a loop IntegerShow = IntegerShow loop IntegerToDouble = IntegerToDouble loop Double = Double loop (DoubleLit a) = DoubleLit a loop DoubleShow = DoubleShow loop Text = Text loop (TextLit (Chunks a b)) = TextLit (Chunks a' b) where a' = fmap (fmap loop) a loop (TextAppend a b) = TextAppend a' b' where a' = loop a b' = loop b loop List = List loop (ListLit a b) = ListLit a' b' where a' = fmap loop a b' = fmap loop b loop (ListAppend a b) = ListAppend a' b' where a' = loop a b' = loop b loop ListBuild = ListBuild loop ListFold = ListFold loop ListLength = ListLength loop ListHead = ListHead loop ListLast = ListLast loop ListIndexed = ListIndexed loop ListReverse = ListReverse loop Optional = Optional loop (Some a) = Some a' where a' = loop a loop None = None loop (OptionalLit _ (Just b)) = loop (Some b) loop (OptionalLit a Nothing) = loop (App None a) loop OptionalFold = OptionalFold loop OptionalBuild = OptionalBuild loop (Record a) = Record a' where a' = fmap loop a loop (RecordLit a) = RecordLit a' where a' = fmap loop a loop (Union a) = Union a' where a' = fmap loop a loop (UnionLit a b c) = UnionLit a b' c' where b' = loop b c' = fmap loop c loop (Combine a b) = Combine a' b' where a' = loop a b' = loop b loop (CombineTypes a b) = CombineTypes a' b' where a' = loop a b' = loop b loop (Prefer a b) = Prefer a' b' where a' = loop a b' = loop b loop (Merge a b c) = Merge a' b' c' where a' = loop a b' = loop b c' = fmap loop c loop (Constructors a) = Constructors a' where a' = loop a loop (Field a b) = Field a' b where a' = loop a loop (Project a b) = Project a' b where a' = loop a loop (Note a _) = absurd a loop (ImportAlt a b) = ImportAlt a' b' where a' = loop a b' = loop b loop (Embed a) = Embed a dhall-1.19.1/src/Dhall/Main.hs0000644000000000000000000003063713377175666014146 0ustar0000000000000000{-| This module contains the top-level entrypoint and options parsing for the @dhall@ executable -} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} module Dhall.Main ( -- * Options Options(..) , Mode(..) , parseOptions , parserInfoOptions -- * Execution , command , main ) where import Control.Applicative (optional, (<|>)) import Control.Exception (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.Import (Imported(..)) import Dhall.Parser (Src) import Dhall.Pretty (Ann, CharacterSet(..), annToAnsiStyle, layoutOpts) import Dhall.TypeCheck (DetailedTypeError(..), TypeError, X) import Lens.Family (set) import Options.Applicative (Parser, ParserInfo) import System.Exit (exitFailure) import System.IO (Handle) import qualified Codec.Serialise import qualified Control.Exception import qualified Control.Monad.Trans.State.Strict as State import qualified Data.ByteString.Lazy 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.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.Pretty import qualified Dhall.Repl import qualified Dhall.TypeCheck import qualified GHC.IO.Encoding import qualified Options.Applicative import qualified Paths_dhall as Meta import qualified System.Console.ANSI import qualified System.IO import qualified Text.Dot -- | Top-level program options data Options = Options { mode :: Mode , explain :: Bool , plain :: Bool , ascii :: Bool , standardVersion :: StandardVersion } -- | The subcommands for the @dhall@ executable data Mode = Default { annotate :: Bool } | Version | Resolve { dot :: Bool } | Type | Normalize | Repl | Format { inplace :: Maybe FilePath } | Freeze { inplace :: Maybe FilePath } | Hash | Diff { expr1 :: Text, expr2 :: Text } | Lint { inplace :: Maybe FilePath } | Encode | Decode -- | `Parser` for the `Options` type parseOptions :: Parser Options parseOptions = Options <$> 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 where switch name description = Options.Applicative.switch ( Options.Applicative.long name <> Options.Applicative.help description ) subcommand :: String -> String -> Parser a -> Parser a subcommand name description parser = Options.Applicative.hsubparser ( Options.Applicative.command name parserInfo <> Options.Applicative.metavar name ) where parserInfo = Options.Applicative.info parser ( Options.Applicative.fullDesc <> Options.Applicative.progDesc description ) parseMode :: Parser Mode parseMode = subcommand "version" "Display version" (pure Version) <|> subcommand "resolve" "Resolve an expression's imports" (Resolve <$> parseDot) <|> subcommand "type" "Infer an expression's type" (pure Type) <|> subcommand "normalize" "Normalize an expression" (pure Normalize) <|> subcommand "repl" "Interpret expressions in a REPL" (pure Repl) <|> subcommand "diff" "Render the difference between the normal form of two expressions" (Diff <$> argument "expr1" <*> argument "expr2") <|> subcommand "hash" "Compute semantic hashes for Dhall expressions" (pure Hash) <|> subcommand "lint" "Improve Dhall code" (Lint <$> optional parseInplace) <|> subcommand "format" "Formatter for the Dhall language" (Format <$> optional parseInplace) <|> subcommand "freeze" "Add hashes to all import statements of an expression" (Freeze <$> optional parseInplace) <|> subcommand "encode" "Encode a Dhall expression to binary" (pure Encode) <|> subcommand "decode" "Decode a Dhall expression from binary" (pure Decode) <|> (Default <$> parseAnnotate) where argument = fmap Data.Text.pack . Options.Applicative.strArgument . Options.Applicative.metavar parseAnnotate = Options.Applicative.switch (Options.Applicative.long "annotate") parseDot = Options.Applicative.switch ( Options.Applicative.long "dot" <> Options.Applicative.help "Output import dependency graph in dot format" ) parseInplace = Options.Applicative.strOption ( Options.Applicative.long "inplace" <> Options.Applicative.help "Modify the specified file in-place" <> Options.Applicative.metavar "FILE" ) throws :: Exception e => Either e a -> IO a throws (Left e) = Control.Exception.throwIO e throws (Right a) = return a getExpression :: IO (Expr Src Import) getExpression = do inText <- Data.Text.IO.getContents throws (Dhall.Parser.exprFromText "(stdin)" inText) -- | `ParserInfo` for the `Options` type parserInfoOptions :: ParserInfo Options parserInfoOptions = Options.Applicative.info (Options.Applicative.helper <*> parseOptions) ( Options.Applicative.progDesc "Interpreter for the Dhall language" <> Options.Applicative.fullDesc ) -- | 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 status = set Dhall.Import.standardVersion standardVersion (Dhall.Import.emptyStatus ".") let handle = Control.Exception.handle handler2 . Control.Exception.handle handler1 . Control.Exception.handle handler0 where handler0 e = do let _ = e :: TypeError Src X System.IO.hPutStrLn System.IO.stderr "" if explain then Control.Exception.throwIO (DetailedTypeError e) else do Data.Text.IO.hPutStrLn System.IO.stderr "\ESC[2mUse \"dhall --explain\" for detailed errors\ESC[0m" Control.Exception.throwIO e handler1 (Imported ps e) = do let _ = e :: TypeError Src X System.IO.hPutStrLn System.IO.stderr "" if explain then Control.Exception.throwIO (Imported ps (DetailedTypeError e)) else do Data.Text.IO.hPutStrLn System.IO.stderr "\ESC[2mUse \"dhall --explain\" for detailed errors\ESC[0m" Control.Exception.throwIO (Imported ps e) handler2 e = do let _ = e :: SomeException System.IO.hPrint System.IO.stderr e System.Exit.exitFailure let renderDoc :: Handle -> Doc Ann -> IO () renderDoc h doc = do let stream = Pretty.layoutSmart layoutOpts doc supportsANSI <- System.Console.ANSI.hSupportsANSI h let ansiStream = if supportsANSI && not plain then fmap annToAnsiStyle stream else Pretty.unAnnotateS stream Pretty.renderIO h ansiStream Data.Text.IO.hPutStrLn h "" let render :: Pretty a => Handle -> Expr s a -> IO () render h expression = do let doc = Dhall.Pretty.prettyCharacterSet characterSet expression renderDoc h doc handle $ case mode of Version -> do putStrLn (showVersion Meta.version) Default {..} -> do expression <- getExpression resolvedExpression <- State.evalStateT (Dhall.Import.loadWith expression) status inferredType <- throws (Dhall.TypeCheck.typeOf resolvedExpression) let normalizedExpression = Dhall.Core.normalize resolvedExpression let annotatedExpression = if annotate then Annot normalizedExpression inferredType else normalizedExpression render System.IO.stdout annotatedExpression Resolve dot -> do expression <- getExpression (resolvedExpression, Dhall.Import.Types.Status { _dot }) <- State.runStateT (Dhall.Import.loadWith expression) status if dot then putStr . ("strict " <>) . Text.Dot.showDot $ Text.Dot.attribute ("rankdir", "LR") >> _dot else render System.IO.stdout resolvedExpression Normalize -> do expression <- getExpression resolvedExpression <- Dhall.Import.assertNoImports expression _ <- throws (Dhall.TypeCheck.typeOf resolvedExpression) render System.IO.stdout (Dhall.Core.normalize resolvedExpression) Type -> do expression <- getExpression resolvedExpression <- Dhall.Import.assertNoImports expression inferredType <- throws (Dhall.TypeCheck.typeOf resolvedExpression) render System.IO.stdout (Dhall.Core.normalize inferredType) Repl -> do Dhall.Repl.repl characterSet explain standardVersion Diff {..} -> do expression1 <- Dhall.inputExpr expr1 expression2 <- Dhall.inputExpr expr2 let diff = Dhall.Diff.diffNormalized expression1 expression2 renderDoc System.IO.stdout diff Format {..} -> do Dhall.Format.format characterSet inplace Freeze {..} -> do Dhall.Freeze.freeze inplace standardVersion Hash -> do Dhall.Hash.hash standardVersion Lint {..} -> do case inplace of Just file -> do text <- Data.Text.IO.readFile file (header, expression) <- throws (Dhall.Parser.exprAndHeaderFromText file text) let lintedExpression = Dhall.Lint.lint expression let doc = Pretty.pretty header <> Dhall.Pretty.prettyCharacterSet characterSet lintedExpression System.IO.withFile file System.IO.WriteMode (\h -> do renderDoc h doc ) Nothing -> do text <- Data.Text.IO.getContents (header, expression) <- throws (Dhall.Parser.exprAndHeaderFromText "(stdin)" text) let lintedExpression = Dhall.Lint.lint expression let doc = Pretty.pretty header <> Dhall.Pretty.prettyCharacterSet characterSet lintedExpression renderDoc System.IO.stdout doc Encode -> do expression <- getExpression let term = Dhall.Binary.encodeWithVersion standardVersion expression let bytes = Codec.Serialise.serialise term Data.ByteString.Lazy.putStr bytes Decode -> do bytes <- Data.ByteString.Lazy.getContents term <- throws (Codec.Serialise.deserialiseOrFail bytes) expression <- throws (Dhall.Binary.decodeWithVersion term) let doc = Dhall.Pretty.prettyCharacterSet characterSet expression renderDoc System.IO.stdout doc -- | Entry point for the @dhall@ executable main :: IO () main = do options <- Options.Applicative.execParser parserInfoOptions command options dhall-1.19.1/src/Dhall/Map.hs0000644000000000000000000003137713377175666014001 0ustar0000000000000000{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE TypeFamilies #-} -- | `Map` type used to represent records and unions module Dhall.Map ( -- * Type Map -- * Construction , singleton , fromList -- * Sorting , sort , isSorted -- * Insertion , insert , insertWith -- * Deletion/Update , delete , filter , mapMaybe -- * Query , lookup , member , uncons -- * Combine , union , unionWith , intersection , intersectionWith , difference -- * Traversals , mapWithKey , traverseWithKey , traverseWithKey_ , foldMapWithKey -- * Conversions , toList , toMap , keys ) where import Control.Applicative ((<|>)) import Data.Data (Data) import Data.Semigroup import Prelude hiding (filter, lookup) import qualified Data.Functor import qualified Data.Map import qualified Data.Set import qualified GHC.Exts import qualified Prelude {-| A `Map` that remembers the original ordering of keys This is primarily used so that formatting preserves field order This is done primarily to avoid a dependency on @insert-ordered-containers@ and also to improve performance -} data Map k v = Map (Data.Map.Map k v) [k] deriving (Data) instance (Eq k, Eq v) => Eq (Map k v) where (Map m1 ks) == (Map m2 ks') = m1 == m2 && ks == ks' {-# INLINABLE (==) #-} 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 {-# INLINABLE foldr #-} foldMap f (Map m _) = foldMap f m {-# INLINABLE foldMap #-} instance Traversable (Map k) where traverse f (Map m ks) = (\m' -> Map m' ks) <$> traverse f m {-# INLINABLE traverse #-} instance Ord k => Data.Semigroup.Semigroup (Map k v) where (<>) = union {-# INLINABLE (<>) #-} instance Ord k => Monoid (Map k v) where mempty = Map Data.Map.empty [] {-# 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) where kvs = toList m instance Ord k => GHC.Exts.IsList (Map k v) where type Item (Map k v) = (k, v) fromList = Dhall.Map.fromList toList = Dhall.Map.toList {-| Create a `Map` from a single key-value pair >>> singleton "A" 1 fromList [("A",1)] -} singleton :: k -> v -> Map k v singleton k v = Map m ks where m = Data.Map.singleton k v ks = pure 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)] -} fromList :: Ord k => [(k, v)] -> Map k v fromList kvs = Map m ks where m = Data.Map.fromList kvs ks = nubOrd (map fst kvs) {-# INLINABLE fromList #-} {-| Remove duplicates from a list >>> nubOrd [1,2,3] [1,2,3] >>> nubOrd [1,1,3] [1,3] -} nubOrd :: Ord k => [k] -> [k] nubOrd = go Data.Set.empty where go _ [] = [] go set (k:ks) | Data.Set.member k set = go set ks | otherwise = k : go (Data.Set.insert k set) ks {-# INLINABLE nubOrd #-} {-| Sort the keys of a `Map`, forgetting the original ordering > sort (sort x) = sort x >>> sort (fromList [("B",1),("A",2)]) fromList [("A",2),("B",1)] -} sort :: Ord k => Map k v -> Map k v sort (Map m _) = Map m ks where ks = Data.Map.keys m {-# INLINABLE sort #-} {-| Check if the keys of a `Map` are already sorted > isSorted (sort m) = True >>> isSorted (fromList [("B",1),("A",2)]) -- Sortedness is based only on keys False >>> isSorted (fromList [("A",2),("B",1)]) True -} isSorted :: Eq k => Map k v -> Bool isSorted (Map m k) = Data.Map.keys m == k {-# INLINABLE isSorted #-} {-| Insert a key-value pair into a `Map`, overriding any previous value stored underneath the same key, if present > insert = insertWith (\v _ -> v) >>> insert "C" 1 (fromList [("B",2),("A",3)]) -- Values are inserted on left fromList [("C",1),("B",2),("A",3)] >>> insert "C" 1 (fromList [("C",2),("A",3)]) -- New value takes precedence fromList [("C",1),("A",3)] -} insert :: Ord k => k -> v -> Map k v -> Map k v insert k v (Map m ks) = Map m' ks' where m' = Data.Map.insert k v m ks' | elem k ks = ks | otherwise = k : ks {-# INLINABLE insert #-} {-| Insert a key-value pair into a `Map`, using the supplied function to combine the new value with any old value underneath the same key, if present >>> insertWith (+) "C" 1 (fromList [("B",2),("A",3)]) -- No collision fromList [("C",1),("B",2),("A",3)] >>> insertWith (+) "C" 1 (fromList [("C",2),("A",3)]) -- Collision fromList [("C",3),("A",3)] -} insertWith :: Ord k => (v -> v -> v) -> k -> v -> Map k v -> Map k v insertWith f k v (Map m ks) = Map m' ks' where m' = Data.Map.insertWith f k v m ks' | elem k ks = ks | otherwise = k : ks {-# INLINABLE insertWith #-} {-| Delete a key from a `Map` if present, otherwise return the original `Map` >>> delete "B" (fromList [("C",1),("B",2),("A",3)]) fromList [("C",1),("A",3)] >>> delete "D" (fromList [("C",1),("B",2),("A",3)]) fromList [("C",1),("B",2),("A",3)] -} delete :: Ord k => k -> Map k v -> Map k v delete k (Map m ks) = Map m' ks' where m' = Data.Map.delete k m ks' = Prelude.filter (k /=) ks {-# INLINABLE delete #-} {-| Keep all values that satisfy the given predicate >>> filter even (fromList [("C",3),("B",2),("A",1)]) fromList [("B",2)] >>> filter odd (fromList [("C",3),("B",2),("A",1)]) fromList [("C",3),("A",1)] -} filter :: Ord k => (a -> Bool) -> Map k a -> Map k a filter predicate (Map m ks) = Map m' ks' where m' = Data.Map.filter predicate m set = Data.Map.keysSet m' ks' = Prelude.filter (\k -> Data.Set.member k set) ks {-# INLINABLE filter #-} {-| Transform all values in a `Map` using the supplied function, deleting the key if the function returns `Nothing` >>> mapMaybe Data.Maybe.listToMaybe (fromList [("C",[1]),("B",[]),("A",[3])]) fromList [("C",1),("A",3)] -} mapMaybe :: Ord k => (a -> Maybe b) -> Map k a -> Map k b mapMaybe f (Map m ks) = Map m' ks' where m' = Data.Map.mapMaybe f m set = Data.Map.keysSet m' ks' = Prelude.filter (\k -> Data.Set.member k set) ks {-# INLINABLE mapMaybe #-} {-| Retrieve a key from a `Map` > lookup k mempty = empty > > lookup k (x <> y) = lookup k y <|> lookup k x >>> lookup "A" (fromList [("B",1),("A",2)]) Just 2 >>> lookup "C" (fromList [("B",1),("A",2)]) Nothing -} lookup :: Ord k => k -> Map k v -> Maybe v lookup k (Map m _) = Data.Map.lookup k m {-# INLINABLE lookup #-} {-| Retrieve the first key, value of the 'Map', if present, and also returning the rest of the 'Map'. > uncons mempty = empty > > uncons (singleton k v) = (k, v, mempty) >>> uncons (fromList [("C",1),("B",2),("A",3)]) Just ("C",1,fromList [("B",2),("A",3)]) >>> uncons (fromList []) Nothing -} uncons :: Ord k => Map k v -> Maybe (k, v, Map k v) uncons (Map _ []) = Nothing uncons (Map m (k:ks)) = Just (k, m Data.Map.! k, Map (Data.Map.delete k m) ks) {-# INLINABLE uncons #-} {-| Check if a key belongs to a `Map` > member k mempty = False > > member k (x <> y) = member k x || member k y >>> member "A" (fromList [("B",1),("A",2)]) True >>> member "C" (fromList [("B",1),("A",2)]) False -} member :: Ord k => k -> Map k v -> Bool member k (Map m _) = Data.Map.member k m {-# INLINABLE member #-} {-| Combine two `Map`s, preferring keys from the first `Map` > union = unionWith (\v _ -> v) >>> union (fromList [("D",1),("C",2)]) (fromList [("B",3),("A",4)]) fromList [("D",1),("C",2),("B",3),("A",4)] >>> union (fromList [("D",1),("C",2)]) (fromList [("C",3),("A",4)]) fromList [("D",1),("C",2),("A",4)] -} union :: Ord k => Map k v -> Map k v -> Map k v union (Map mL ksL) (Map mR ksR) = Map m ks where m = Data.Map.union mL mR setL = Data.Map.keysSet mL ks = ksL <|> Prelude.filter (\k -> Data.Set.notMember k setL) ksR {-# INLINABLE union #-} {-| Combine two `Map`s using a combining function for colliding keys >>> unionWith (+) (fromList [("D",1),("C",2)]) (fromList [("B",3),("A",4)]) fromList [("D",1),("C",2),("B",3),("A",4)] >>> unionWith (+) (fromList [("D",1),("C",2)]) (fromList [("C",3),("A",4)]) fromList [("D",1),("C",5),("A",4)] -} unionWith :: Ord k => (v -> v -> v) -> Map k v -> Map k v -> Map k v unionWith combine (Map mL ksL) (Map mR ksR) = Map m ks where m = Data.Map.unionWith combine mL mR setL = Data.Map.keysSet mL ks = ksL <|> Prelude.filter (\k -> Data.Set.notMember k setL) ksR {-# INLINABLE unionWith #-} {-| Combine two `Map` on their shared keys, keeping the value from the first `Map` > intersection = intersectionWith (\v _ -> v) >>> intersection (fromList [("C",1),("B",2)]) (fromList [("B",3),("A",4)]) fromList [("B",2)] -} intersection :: Ord k => Map k a -> Map k b -> Map k a intersection (Map mL ksL) (Map mR _) = Map m ks where m = Data.Map.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 {-# INLINABLE intersection #-} {-| Combine two `Map`s on their shared keys, using the supplied function to combine values from the first and second `Map` >>> intersectionWith (+) (fromList [("C",1),("B",2)]) (fromList [("B",3),("A",4)]) fromList [("B",5)] -} intersectionWith :: Ord k => (a -> b -> c) -> Map k a -> Map k b -> Map k c intersectionWith combine (Map mL ksL) (Map mR _) = Map m ks where m = Data.Map.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 {-# INLINABLE intersectionWith #-} {-| Compute the difference of two `Map`s by subtracting all keys from the second `Map` from the first `Map` >>> difference (fromList [("C",1),("B",2)]) (fromList [("B",3),("A",4)]) fromList [("C",1)] -} difference :: Ord k => Map k a -> Map k b -> Map k a difference (Map mL ksL) (Map mR _) = Map m ks where m = Data.Map.difference mL mR setR = Data.Map.keysSet mR ks = Prelude.filter (\k -> Data.Set.notMember k setR) ksL {-# INLINABLE difference #-} {-| Fold all of the key-value pairs in a `Map`, in their original order >>> foldMapWithKey (,) (fromList [("B",[1]),("A",[2])]) ("BA",[1,2]) -} foldMapWithKey :: (Monoid m, Ord k) => (k -> a -> m) -> Map k a -> m foldMapWithKey f m = foldMap (uncurry f) (toList m) {-# INLINABLE foldMapWithKey #-} {-| Transform the values of a `Map` using their corresponding key > mapWithKey (pure id) = id > > mapWithKey (liftA2 (.) f g) = mapWithKey f . mapWithKey g > mapWithKey f mempty = mempty > > mapWithKey f (x <> y) = mapWithKey f x <> mapWithKey f y >>> mapWithKey (,) (fromList [("B",1),("A",2)]) fromList [("B",("B",1)),("A",("A",2))] -} mapWithKey :: (k -> a -> b) -> Map k a -> Map k b mapWithKey f (Map m ks) = Map m' ks where m' = Data.Map.mapWithKey f m {-# INLINABLE mapWithKey #-} {-| Traverse all of the key-value pairs in a `Map`, in their original order >>> traverseWithKey (,) (fromList [("B",1),("A",2)]) ("BA",fromList [("B",1),("A",2)]) -} traverseWithKey :: Ord k => Applicative f => (k -> a -> f b) -> Map k a -> f (Map k b) traverseWithKey f m = fmap 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) -} traverseWithKey_ :: Ord k => Applicative f => (k -> a -> f ()) -> Map k a -> f () traverseWithKey_ f m = Data.Functor.void (traverseWithKey f m) {-# INLINABLE traverseWithKey_ #-} {-| Convert a `Map` to a list of key-value pairs in the original order of keys >>> toList (fromList [("B",1),("A",2)]) [("B",1),("A",2)] -} toList :: Ord k => Map k v -> [(k, v)] toList (Map m ks) = fmap (\k -> (k, m Data.Map.! k)) ks {-# INLINABLE toList #-} {-| Convert a @"Dhall.Map".`Map`@ to a @"Data.Map".`Data.Map.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 m _) = m {-# INLINABLE toMap #-} {-| Return the keys from a `Map` in their original order >>> keys (fromList [("B",1),("A",2)]) ["B","A"] -} keys :: Map k v -> [k] keys (Map _ ks) = ks {-# INLINABLE keys #-} dhall-1.19.1/src/Dhall/Parser.hs0000644000000000000000000000513213377175666014506 0ustar0000000000000000{-# LANGUAGE RecordWildCards #-} -- | This module contains Dhall's parsing logic module Dhall.Parser ( -- * Utilities exprFromText , exprAndHeaderFromText -- * Parsers , expr, exprA -- * Types , Src(..) , ParseError(..) , Parser(..) ) where import Control.Exception (Exception) import Data.Semigroup (Semigroup(..)) import Data.Text (Text) import Data.Void (Void) import Dhall.Core import Prelude hiding (const, pi) import qualified Data.Text import qualified Text.Megaparsec import Dhall.Parser.Combinators import Dhall.Parser.Token import Dhall.Parser.Expression -- | Parser for a top-level Dhall expression expr :: Parser (Expr Src Import) expr = exprA import_ -- | Parser for a top-level Dhall expression. The expression is parameterized -- over any parseable type, allowing the language to be extended as needed. exprA :: Parser a -> Parser (Expr Src a) exprA = completeExpression -- | A parsing error data ParseError = ParseError { unwrap :: Text.Megaparsec.ParseErrorBundle Text Void , input :: Text } instance Show ParseError where show (ParseError {..}) = "\n\ESC[1;31mError\ESC[0m: Invalid input\n\n" <> Text.Megaparsec.errorBundlePretty unwrap instance Exception ParseError -- | Parse an expression from `Text` containing a Dhall program exprFromText :: String -- ^ User-friendly name describing the input expression, -- used in parsing error messages -> Text -- ^ Input expression to parse -> Either ParseError (Expr Src Import) exprFromText delta text = fmap snd (exprAndHeaderFromText delta text) {-| 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) exprAndHeaderFromText delta text = case result of Left errInfo -> Left (ParseError { unwrap = errInfo, input = text }) Right (txt, r) -> Right (Data.Text.dropWhileEnd (/= '\n') txt, r) where parser = do (bytes, _) <- Text.Megaparsec.match whitespace r <- expr Text.Megaparsec.eof return (bytes, r) result = Text.Megaparsec.parse (unParser parser) delta text dhall-1.19.1/src/Dhall/Pretty.hs0000644000000000000000000000103613377175666014540 0ustar0000000000000000{-| This module contains logic for pretty-printing expressions, including support for syntax highlighting -} module Dhall.Pretty ( -- * Pretty Ann(..) , annToAnsiStyle , prettyExpr , CharacterSet(..) , prettyCharacterSet , layoutOpts ) 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 } dhall-1.19.1/src/Dhall/Repl.hs0000644000000000000000000001550613377175666014162 0ustar0000000000000000-- | This module contains the implementation of the @dhall repl@ subcommand {-# language FlexibleContexts #-} {-# language NamedFieldPuns #-} {-# language OverloadedStrings #-} module Dhall.Repl ( -- * Repl repl ) where import Control.Exception ( SomeException(SomeException), displayException, throwIO ) import Control.Monad.IO.Class ( MonadIO, liftIO ) import Control.Monad.State.Class ( MonadState, get, modify ) import Control.Monad.State.Strict ( evalStateT ) import Data.List ( foldl' ) import Dhall.Binary (StandardVersion(..)) import Dhall.Import (standardVersion) import Dhall.Pretty (CharacterSet(..)) import Lens.Family (set) import qualified Control.Monad.Trans.State.Strict as State import qualified Data.Text as Text import qualified Data.Text.Prettyprint.Doc as Pretty import qualified Data.Text.Prettyprint.Doc.Render.Terminal as Pretty ( renderIO ) 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.Pretty import qualified Dhall.Core as Expr ( Expr(..) ) import qualified Dhall.Import as Dhall import qualified Dhall.Parser as Dhall import qualified Dhall.TypeCheck as Dhall import qualified System.Console.ANSI import qualified System.Console.Haskeline.MonadException as Haskeline import qualified System.Console.Repline as Repline import qualified System.IO -- | Implementation of the @dhall repl@ subcommand repl :: CharacterSet -> Bool -> StandardVersion -> IO () repl characterSet explain _standardVersion = if explain then Dhall.detailed io else io where io = evalStateT ( Repline.evalRepl ( pure "⊢ " ) ( dontCrash . eval ) options (Just ':') ( Repline.Word completer ) greeter ) (emptyEnv { characterSet, explain, _standardVersion }) data Env = Env { envBindings :: Dhall.Context.Context Binding , envIt :: Maybe Binding , explain :: Bool , characterSet :: CharacterSet , _standardVersion :: StandardVersion } emptyEnv :: Env emptyEnv = Env { envBindings = Dhall.Context.empty , envIt = Nothing , explain = False , _standardVersion = Dhall.Binary.defaultStandardVersion , characterSet = Unicode } data Binding = Binding { bindingExpr :: Dhall.Expr Dhall.Src Dhall.X , bindingType :: Dhall.Expr Dhall.Src Dhall.X } envToContext :: Env -> Dhall.Context.Context Binding envToContext Env{ envBindings, envIt } = case envIt of Nothing -> envBindings Just it -> Dhall.Context.insert "it" it envBindings parseAndLoad :: ( MonadIO m, MonadState Env m ) => String -> m ( Dhall.Expr Dhall.Src Dhall.X ) parseAndLoad src = do env <- get parsed <- case Dhall.exprFromText "(stdin)" ( Text.pack src ) of Left e -> liftIO ( throwIO e ) Right a -> return a let status = set standardVersion (_standardVersion env) (Dhall.emptyStatus ".") liftIO ( State.evalStateT (Dhall.loadWith parsed) status ) eval :: ( MonadIO m, MonadState Env m ) => String -> m () eval src = do loaded <- parseAndLoad src exprType <- typeCheck loaded expr <- normalize loaded modify ( \e -> e { envIt = Just ( Binding expr exprType ) } ) output System.IO.stdout expr typeOf :: ( MonadIO m, MonadState Env m ) => [String] -> m () typeOf [] = liftIO ( putStrLn ":type requires an argument to check the type of" ) typeOf srcs = do loaded <- parseAndLoad ( unwords srcs ) exprType <- typeCheck loaded exprType' <- normalize exprType output System.IO.stdout exprType' normalize :: MonadState Env m => Dhall.Expr Dhall.Src Dhall.X -> m ( Dhall.Expr t Dhall.X ) normalize e = do env <- get return ( Dhall.normalize ( foldl' ( \a (k, Binding { bindingType, bindingExpr }) -> Expr.Let (pure (Dhall.Core.Binding k (Just bindingType) bindingExpr)) a ) e ( Dhall.Context.toList ( envToContext env ) ) ) ) typeCheck :: ( MonadIO m, MonadState Env m ) => Dhall.Expr Dhall.Src Dhall.X -> m ( Dhall.Expr Dhall.Src Dhall.X ) typeCheck expr = do env <- get let wrap = if explain env then Dhall.detailed else id case Dhall.typeWith ( bindingType <$> envToContext env ) expr of Left e -> liftIO ( wrap (throwIO e) ) Right a -> return a addBinding :: ( MonadIO m, MonadState Env m ) => [String] -> m () addBinding (k : "=" : srcs) = do let varName = Text.pack k loaded <- parseAndLoad ( unwords srcs ) t <- typeCheck loaded expr <- normalize loaded modify ( \e -> e { envBindings = Dhall.Context.insert varName Binding { bindingType = t, bindingExpr = expr } ( envBindings e ) } ) output System.IO.stdout ( Expr.Annot ( Expr.Var ( Dhall.V varName 0 ) ) t ) addBinding _ = liftIO ( fail ":let should be of the form `:let x = y`" ) saveBinding :: ( MonadIO m, MonadState Env m ) => [String] -> m () saveBinding (file : "=" : tokens) = do loadedExpression <- parseAndLoad (unwords tokens) _ <- typeCheck loadedExpression normalizedExpression <- normalize loadedExpression env <- get let handler handle = State.evalStateT (output handle normalizedExpression) env liftIO (System.IO.withFile file System.IO.WriteMode handler) saveBinding _ = fail ":save should be of the form `:save x = y`" options :: ( Haskeline.MonadException m, MonadIO m, MonadState Env m ) => Repline.Options m options = [ ( "type", dontCrash . typeOf ) , ( "let", dontCrash . addBinding ) , ( "save", dontCrash . saveBinding ) ] completer :: Monad m => Repline.WordCompleter m completer _ = return [] greeter :: MonadIO m => m () greeter = return () dontCrash :: ( MonadIO m, Haskeline.MonadException m ) => m () -> m () dontCrash m = Haskeline.catch m ( \ e@SomeException{} -> liftIO ( putStrLn ( displayException e ) ) ) output :: (Pretty.Pretty a, MonadState Env m, MonadIO m) => System.IO.Handle -> Dhall.Expr s a -> m () output handle expr = do Env { characterSet } <- get liftIO (System.IO.hPutStrLn handle "") -- Visual spacing let stream = Pretty.layoutSmart Dhall.Pretty.layoutOpts (Dhall.Pretty.prettyCharacterSet characterSet expr) supportsANSI <- liftIO (System.Console.ANSI.hSupportsANSI handle) let ansiStream = if supportsANSI then fmap Dhall.Pretty.annToAnsiStyle stream else Pretty.unAnnotateS stream liftIO (Pretty.renderIO handle ansiStream) liftIO (System.IO.hPutStrLn handle "") -- Pretty printing doesn't end with a new line liftIO (System.IO.hPutStrLn handle "") -- Visual spacing dhall-1.19.1/src/Dhall/Set.hs0000644000000000000000000000342213377175666014005 0ustar0000000000000000{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} -- | This module only exports ways of constructing a Set, -- retrieving List, Set, and Seq representations of the same data, -- as well as a novel "difference" function. -- Any other Set-like or List-like functionality -- should be obtained through toSet and toList, respectively. module Dhall.Set ( Set(..) , toList , toSet , toSeq , fromList , append , empty , difference ) where import Prelude import Data.List (foldl') import Data.Sequence (Seq, (|>)) import Data.Data (Data) import GHC.Generics (Generic) import qualified Data.Set import qualified Data.Sequence import qualified Data.Foldable data Set a = Set (Data.Set.Set a) (Seq a) deriving (Eq, Generic, Ord, Show, Data) instance Foldable Set where foldMap f = foldMap f . toSeq toSet :: Set a -> Data.Set.Set a toSet (Set s _) = s toSeq :: Set a -> Seq a toSeq (Set _ xs) = xs toList :: Set a -> [a] toList = Data.Foldable.toList -- 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. 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) empty :: Set a empty = Set Data.Set.empty Data.Sequence.empty -- | Returns, in order, all elements of the first Set not present in the second. -- (It doesn't matter in what order the elements appear in the second Set.) difference :: Ord a => Set a -> Set a -> [a] difference os (Set s _) = filter (\ x -> not (Data.Set.member x s)) (toList os) dhall-1.19.1/src/Dhall/TH.hs0000644000000000000000000000340113377175666013562 0ustar0000000000000000{-# 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. 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: > Dhall.Type > (\case > UnionLit "This" _ _ -> ... > UnionLit "Other" _ _ -> ...) > $(staticDhallExpression "./Some/Type.dhall") This would create the Dhall Expr AST from the @".\/Some\/Type.dhall"@ file at compile time with all imports resolved, making it easy to keep your Dhall configs and Haskell interpreters in sync. -} module Dhall.TH ( -- * Template Haskell staticDhallExpression ) where import Data.Typeable import Language.Haskell.TH.Quote (dataToExpQ) -- 7.10 compatibility. import Language.Haskell.TH.Syntax import qualified Data.Text as Text import qualified Dhall import qualified GHC.IO.Encoding import qualified System.IO -- | 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 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 dhall-1.19.1/src/Dhall/Tutorial.hs0000644000000000000000000024177313377175666015072 0ustar0000000000000000{-# OPTIONS_GHC -fno-warn-unused-imports #-} {-| Dhall is a programming language specialized for configuration files. This module contains a tutorial explaning how to author configuration files using this language -} module Dhall.Tutorial ( -- * Introduction -- $introduction -- * Types -- $types -- * Imports -- $imports -- * Lists -- $lists -- * Optional values -- $optional0 -- * Records -- $records -- * Functions -- $functions -- * Compiler -- $compiler -- * Strings -- $strings -- * Combine -- $combine -- * Let expressions -- $let -- * Unions -- $unions -- * Polymorphic functions -- $polymorphic -- * Total -- $total -- * Headers -- $headers -- * Import integrity -- $integrity -- * Raw text -- $rawText -- * Formatting code -- $format -- * Built-in functions -- $builtins -- ** Caveats -- $caveats -- ** Overview -- $builtinOverview -- ** @Bool@ -- $bool -- *** @(||)@ -- $or -- *** @(&&)@ -- $and -- *** @(==)@ -- $equal -- *** @(!=)@ -- $unequal -- *** @if@\/@then@\/@else@ -- $ifthenelse -- ** @Natural@ -- $natural -- *** @(+)@ -- $plus -- *** @(*)@ -- $times -- *** @Natural/even@ -- $even -- *** @Natural/odd@ -- $odd -- *** @Natural/isZero@ -- $isZero -- *** @Natural/fold@ -- $naturalFold -- *** @Natural/build@ -- $naturalBuild -- ** @Integer@ -- $integer -- ** @Double@ -- $double -- ** @Text@ -- $text -- *** @(++)@ -- $textAppend -- ** @List@ -- $list -- *** @(#)@ -- $listAppend -- *** @List/fold@ -- $listFold -- *** @List/build@ -- $listBuild -- *** @List/length@ -- $listLength -- *** @List/head@ -- $listHead -- *** @List/last@ -- $listLast -- *** @List/indexed@ -- $listIndexed -- *** @List/reverse@ -- $listReverse -- ** @Optional@ -- $optional1 -- *** @Optional/fold@ -- $optionalFold -- * Prelude -- $prelude -- * Conclusion -- $conclusion -- * Frequently Asked Questions (FAQ) -- $faq ) where import Data.Vector (Vector) import Dhall -- $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 : 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 < { 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: -- -- -- -- > $ 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: -- -- -- -- 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 -- ... -- [] -- (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 -- ... -- 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 -- > {=} -- > -- > {} -- > -- > {=} -- -- > $ dhall -- > {} -- > -- > 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 } -- > -- > { 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 ] -- > -- -- ... 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 ] -- > -- -- 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 -- > -- > ∀(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 -- > -- > 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 -- > -- > 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\"!" -- > -- > Text -- > -- > "Hello, \"world\"!" -- -- ... and Dhall also supports Nix-style multi-line string literals: -- -- > dhall -- > '' -- > #!/bin/bash -- > -- > echo "Hi!" -- > '' -- > -- > 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}" -- > -- > 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 } -- > -- > { bar : Text, baz : Bool, foo : Natural } -- > -- > { bar = "ABC", baz = True, foo = 1 } -- > $ dhall -- > { foo = 1, bar = "ABC" } ⫽ { bar = True } -- Fancy unicode -- > -- > { 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 } } -- > -- > { 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 } -- > -- > 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 } -- > -- > { 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 } -- > -- > { 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 -- > -- > 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 -- > -- > 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 -- > -- > 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" -- > -- > 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" -- > -- > 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 -- > -- > Bool -- > -- > False -- -- ... or to define synonyms for types: -- -- > $ dhall <<< 'let Name : Type = Text in [ "John", "Mary" ] : List Name' -- > List Text -- > -- > [ "John", "Mary" ] -- -- __Exercise:__ What do you think the following code will normalize to? -- -- > let x = 1 -- > in let x = 2 -- > in x -- -- Test your guess using the @dhall@ compiler -- -- __Exercise:__ Now try to guess what this code will normalize to: -- -- > let x = "ha" -- > in let x = x ++ "ha" -- > in x -- -- __Exercise:__ What about this code? -- -- > let x = x ++ "ha" -- > in x -- $unions -- -- A union is a value that can be one of many alternative types of values. For -- example, the following union type: -- -- > < Left : Natural | Right : Bool > -- -- ... represents a value that can be either a @Natural@ or a @Bool@ value. If -- you are familiar with Haskell these are exactly analogous to Haskell's -- \"sum types\". -- -- Each alternative is associated with a tag that distinguishes that alternative -- from other alternatives. In the above example, the @Left@ tag is used for -- the @Natural@ alternative and the @Right@ tag is used for the @Bool@ -- alternative. -- -- A union literal specifies the value of one alternative and the types of the -- remaining alternatives. For example, both of the following union literals -- have the same type, which is the above union type: -- -- > < Left = 0 | Right : Bool > -- -- > < Right = True | Left : Natural > -- -- You can consume a union using the built-in @merge@ function. For example, -- suppose we want to convert our union to a @Bool@ but we want to behave -- differently depending on whether or not the union is a @Natural@ wrapped in -- the @Left@ alternative or a @Bool@ wrapped in the @Right@ alternative. We -- would write: -- -- > $ cat > process < λ(union : < Left : Natural | Right : Bool >) -- > → let handlers = -- > { Left = Natural/even -- Natural/even is a built-in function -- > , Right = λ(b : Bool) → b -- > } -- > in merge handlers union : Bool -- > EOF -- -- Now our @./process@ function can handle both alternatives: -- -- > $ dhall -- > ./process < Left = 3 | Right : Bool > -- > -- > Bool -- > -- > False -- -- > $ dhall -- > ./process < Right = True | Left : Natural > -- > -- > Bool -- > -- > True -- -- Every @merge@ has the following form: -- -- > merge handlers union : type -- -- ... where: -- -- * @union@ is the union you want to consume -- * @handlers@ is a record with one function per alternative of the union -- * @type@ is the declared result type of the @merge@ -- -- The @merge@ function selects which function to apply from the record based on -- which alternative the union selects: -- -- > merge { Foo = f, ... } < Foo = x | ... > : t = f x : t -- -- So, for example: -- -- > merge { Left = Natural/even, Right = λ(b : Bool) → b } < Left = 3 | Right : Bool > : Bool -- > = Natural/even 3 : Bool -- > = False -- -- ... and similarly: -- -- > merge { Left = Natural/even, Right = λ(b : Bool) → b } < Right = True | Left : Natural > : Bool -- > = (λ(b : Bool) → b) True : Bool -- > = True -- -- Notice that each handler has to return the same type of result (@Bool@ in -- this case) which must also match the declared result type of the @merge@. -- -- You can also omit the type annotation when merging a union with one or more -- alternatives, like this: -- -- > merge { Left = Natural/even, Right = λ(b : Bool) → b } < Right = True | Left : Natural > -- -- You can also store more than one value or less than one value within -- alternatives using Dhall's support for anonymous records. You can nest an -- anonymous record within a union such as in this type: -- -- > < Empty : {} | Person : { name : Text, age : Natural } > -- -- This union of records resembles following equivalent Haskell data type: -- -- > data Example = Empty | Person { name :: Text, age :: Text } -- -- You can resemble Haskell further by defining convenient constructors for each -- alternative, like this: -- -- > let Empty = < Empty = {=} | Person : { name : Text, age : Natural } > -- > in let Person = -- > λ(p : { name : Text, age : Natural }) → < Person = p | Empty : {} > -- > in [ Empty -- > , Person { name = "John", age = 23 } -- > , Person { name = "Amy" , age = 25 } -- > , Empty -- > ] -- -- ... and Dhall even provides the @constructors@ keyword to automate this -- common pattern: -- -- > let MyType = constructors < Empty : {} | Person : { name : Text, age : Natural } > -- > in [ MyType.Empty {=} -- > , MyType.Person { name = "John", age = 23 } -- > , MyType.Person { name = "Amy" , age = 25 } -- > ] -- -- The @constructors@ keyword takes a union type argument and returns a record -- with one field per union type constructor: -- -- > $ dhall -- > constructors < Empty : {} | Person : { name : Text, age : Natural } > -- > -- > -- > { Empty : -- > ∀(Empty : {}) → < Empty : {} | Person : { age : Natural, name : Text } > -- > , Person : -- > ∀(Person : { age : Natural, name : Text }) -- > → < Empty : {} | Person : { age : Natural, name : Text } > -- > } -- > -- > { Empty = -- > λ(Empty : {}) → < Empty = Empty | Person : { age : Natural, name : Text } > -- > , Person = -- > λ(Person : { age : Natural, name : Text }) -- > → < Person = Person | Empty : {} > -- > } -- -- You can also extract fields during pattern matching such as in the following -- function which renders each value to `Text`: -- -- > λ(x : < Empty : {} | Person : { name : Text, age : Natural } >) -- > → merge -- > { Empty = λ(_ : {}) → "Unknown" -- > -- > , Person = -- > λ(person : { name : Text, age : Natural }) -- > → "Name: ${person.name}, Age: ${Natural/show person.age}" -- > } -- > x -- -- __Exercise__: Create a list of the following type with at least one element -- per alternative: -- -- > List < Left : 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 -- > -- > ∀(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 -- > -- > ∀(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 -- > -- > ∀(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 -- > -- > Natural -- > -- > 4 -- -- > $ dhall -- > ./id Bool True -- > -- > 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 -- > -- > ∀(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 -- > -- > List Bool → List Bool -- > -- > List/reverse Bool -- -- ... and the second argument is the list to reverse: -- -- > $ dhall -- > List/reverse Bool [True, False] -- > -- > 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 -- > -- > 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 -- > -- > ∀(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] -- > -- > ∀(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) -- > -- > Optional Natural -- > -- > None Natural -- -- __Exercise__: The Dhall Prelude provides a @replicate@ function which you can -- find here: -- -- -- -- 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 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)) -- > -- > 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 -- > -- > {- 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)) -- > -- > 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 -- > -- > Use "dhall --explain" for detailed errors -- > -- > Error: ❰+❱ only works on ❰Natural❱s -- > -- > +2 + +2 -- > -- > (stdin):1:1 -- -- In fact, there are no built-in functions for @Integer@s (or @Double@s). As -- far as the language is concerned they are opaque values that can only be -- shuffled around but not used in any meaningful way until they have been -- loaded into Haskell. -- -- Second, the equality @(==)@ and inequality @(!=)@ operators only work on -- @Bool@s. You cannot test any other types of values for equality. -- $builtinOverview -- -- Each of the following sections provides an overview of builtin functions and -- operators for each type. For each function you get: -- -- * An example use of that function -- -- * A \"type judgement\" explaining when that function or operator is well -- typed -- -- For example, for the following judgement: -- -- > Γ ⊢ x : Bool Γ ⊢ y : Bool -- > ─────────────────────────── -- > Γ ⊢ x && y : Bool -- -- ... you can read that as saying: "if @x@ has type @Bool@ and @y@ has type -- @Bool@, then @x && y@ has type @Bool@" -- -- Similarly, for the following judgement: -- -- > ───────────────────────────────── -- > Γ ⊢ Natural/even : Natural → Bool -- -- ... you can read that as saying: "@Natural/even@ always has type -- @Natural → Bool@" -- -- * Rules for how that function or operator behaves -- -- These rules are just equalities that come in handy when reasoning about code. -- For example, the section on @(&&)@ has the following rules: -- -- > (x && y) && z = x && (y && z) -- > -- > x && True = x -- > -- > True && x = x -- -- These rules are also a contract for how the compiler should behave. If you -- ever observe code that does not obey these rules you should file a bug -- report. -- $bool -- -- There are two values that have type @Bool@ named @True@ and @False@: -- -- > ─────────────── -- > Γ ⊢ True : Bool -- -- > ──────────────── -- > Γ ⊢ False : Bool -- -- The built-in operations for values of type @Bool@ are: -- -- $or -- -- Example: -- -- > $ dhall -- > True || False -- > -- > 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 -- > -- > 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 -- > -- > 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 -- > -- > 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 -- > -- > 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 -- > -- > 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 -- > -- > 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 -- > -- > 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 -- > -- > 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 -- > -- > 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" -- > -- > 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)) -- > -- > 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!" -- > -- > 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] -- > -- > 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 -- > -- > 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))) -- > -- > 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] -- > -- > 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] -- > -- > 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] -- > -- > 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"] -- > -- > 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] -- > -- > 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) "" -- > -- > 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: -- -- -- -- ... which currenty redirects to: -- -- -- -- 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: -- -- -- -- 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 -- > -- > 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 -- > -- > 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: -- -- -- -- __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) -- > -- > ∀(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: -- -- -- -- 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: -- -- dhall-1.19.1/src/Dhall/TypeCheck.hs0000644000000000000000000106175013377175666015142 0ustar0000000000000000{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE RecordWildCards #-} {-# OPTIONS_GHC -Wall #-} -- | This module contains the logic for type checking Dhall code module Dhall.TypeCheck ( -- * Type-checking typeWith , typeOf , typeWithA , checkContext -- * Types , Typer , X(..) , TypeError(..) , DetailedTypeError(..) , TypeMessage(..) ) where import Control.Exception (Exception) import Data.Data (Data(..)) import Data.Foldable (forM_, toList) import Data.List.NonEmpty (NonEmpty(..)) 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.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 => 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 _ 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 Type -> return Type Const Kind -> return Kind Const Sort | Dhall.Core.judgmentallyEqual t0 (Const Kind) -> return Sort _ -> Left (TypeError ctx e (InvalidFieldType k0 t0)) let process k t = do s <- fmap Dhall.Core.normalize (loop ctx t) case s of Const Type -> if c == Type then return () else Left (TypeError ctx e (FieldAnnotationMismatch k t c k0 t0 Type)) Const Kind -> if c == Kind then return () else Left (TypeError ctx e (FieldAnnotationMismatch k t c k0 t0 Kind)) Const Sort -> if c == Sort then if Dhall.Core.judgmentallyEqual t (Const Kind) then return () else Left (TypeError ctx e (InvalidFieldType k t)) else Left (TypeError ctx e (FieldAnnotationMismatch k t c k0 t0 Sort)) _ -> Left (TypeError ctx e (InvalidFieldType k t)) Dhall.Map.traverseWithKey_ process rest case c of Type -> return (Const Type) Kind -> return (Const Sort) Sort -> return (Const Sort) 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 Type -> return Type Const Kind -> return Kind Const Sort | Dhall.Core.judgmentallyEqual t0 (Const Kind) -> return Sort _ -> 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 Type -> if c == Type then return () else Left (TypeError ctx e (FieldMismatch k v c k0 v0 Type)) Const Kind -> if c == Kind then return () else Left (TypeError ctx e (FieldMismatch k v c k0 v0 Kind)) Const Sort -> if c == Sort then if Dhall.Core.judgmentallyEqual t (Const Kind) then return () else Left (TypeError ctx e (InvalidField k t)) else Left (TypeError ctx e (FieldMismatch k v c k0 v0 Sort)) _ -> 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 process k t = do s <- fmap Dhall.Core.normalize (loop ctx t) case s of Const Type -> return () Const Kind -> return () _ -> Left (TypeError ctx e (InvalidAlternativeType k t)) Dhall.Map.traverseWithKey_ process kts return (Const Type) 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 (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 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 (Just t)) = do _ <- loop ctx t tKvsX <- fmap Dhall.Core.normalize (loop ctx kvsX) ktsX <- case tKvsX of Record kts -> return kts _ -> Left (TypeError ctx e (MustMergeARecord kvsX tKvsX)) let ksX = Data.Set.fromList (Dhall.Map.keys ktsX) tKvsY <- fmap Dhall.Core.normalize (loop ctx kvsY) ktsY <- case tKvsY of Union kts -> return kts _ -> Left (TypeError ctx e (MustMergeUnion kvsY tKvsY)) let ksY = Data.Set.fromList (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)) let process (kY, tY) = do case Dhall.Map.lookup kY ktsX of Nothing -> Left (TypeError ctx e (MissingHandler diffY)) Just tX -> case tX of Pi y tY' t' -> do if Dhall.Core.judgmentallyEqual tY tY' then return () else Left (TypeError ctx e (HandlerInputTypeMismatch kY tY tY')) let t'' = Dhall.Core.shift (-1) (V y 0) t' if Dhall.Core.judgmentallyEqual t t'' then return () else Left (TypeError ctx e (InvalidHandlerOutputType kY t t'')) _ -> Left (TypeError ctx e (HandlerNotAFunction kY tX)) mapM_ process (Dhall.Map.toList ktsY) return t loop ctx e@(Merge kvsX kvsY Nothing) = do tKvsX <- fmap Dhall.Core.normalize (loop ctx kvsX) ktsX <- case tKvsX of Record kts -> return kts _ -> Left (TypeError ctx e (MustMergeARecord kvsX tKvsX)) let ksX = Data.Set.fromList (Dhall.Map.keys ktsX) tKvsY <- fmap Dhall.Core.normalize (loop ctx kvsY) ktsY <- case tKvsY of Union kts -> return kts _ -> Left (TypeError ctx e (MustMergeUnion kvsY tKvsY)) let ksY = Data.Set.fromList (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)) (kX, t) <- case Dhall.Map.toList ktsX of [] -> Left (TypeError ctx e MissingMergeType) (kX, Pi y _ t):_ -> return (kX, Dhall.Core.shift (-1) (V y 0) t) (kX, tX ):_ -> Left (TypeError ctx e (HandlerNotAFunction kX tX)) let process (kY, tY) = do case Dhall.Map.lookup kY ktsX of Nothing -> Left (TypeError ctx e (MissingHandler diffY)) Just tX -> case tX of Pi y tY' t' -> do if Dhall.Core.judgmentallyEqual tY tY' then return () else Left (TypeError ctx e (HandlerInputTypeMismatch kY tY tY')) let t'' = Dhall.Core.shift (-1) (V y 0) t' if Dhall.Core.judgmentallyEqual t t'' then return () else Left (TypeError ctx e (HandlerOutputTypeMismatch kX t kY t'')) _ -> Left (TypeError ctx e (HandlerNotAFunction kY tX)) mapM_ process (Dhall.Map.toList ktsY) return t loop ctx e@(Constructors t ) = do _ <- loop ctx t kts <- case Dhall.Core.normalize t of Union kts -> return kts t' -> Left (TypeError ctx e (ConstructorsRequiresAUnionType t t')) let adapt k t_ = Pi k t_ (Union kts) return (Record (Dhall.Map.mapWithKey adapt kts)) 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)) Const Type -> do case Dhall.Core.normalize r of Union kts -> case Dhall.Map.lookup x kts of Just t' -> return (Pi x t' (Union kts)) Nothing -> Left (TypeError ctx e (MissingField x t)) r' -> Left (TypeError ctx e (CantAccess text r' t)) _ -> do Left (TypeError ctx e (CantAccess text r t)) loop ctx e@(Project r 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 (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 -- | 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) | 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) | 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) => TypeMessage s a -> Doc Ann shortTypeMessage msg = "\ESC[1;31mError\ESC[0m: " <> short <> "\n" where ErrorMessages {..} = prettyTypeMessage msg longTypeMessage :: (Eq a, Pretty a) => TypeMessage s a -> Doc Ann longTypeMessage msg = "\ESC[1;31mError\ESC[0m: " <> short <> "\n" <> "\n" <> long where ErrorMessages {..} = prettyTypeMessage msg 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 expression = "↳ " <> Pretty.align (Dhall.Util.snipDoc (Pretty.pretty expression)) prettyDiff :: (Eq a, Pretty a) => Expr s a -> Expr s a -> Doc Ann prettyDiff exprL exprR = Dhall.Diff.diffNormalized exprL exprR prettyTypeMessage :: (Eq a, Pretty a) => TypeMessage s a -> ErrorMessages prettyTypeMessage (UnboundVariable x) = ErrorMessages {..} -- We do not need to print variable name here. For the discussion see: -- https://github.com/dhall-lang/dhall-haskell/pull/116 where short = "Unbound variable: " <> Pretty.pretty x long = "Explanation: Expressions can only reference previously introduced (i.e. “bound”)\n\ \variables that are still “in scope” \n\ \ \n\ \For example, the following valid expressions introduce a “bound” variable named \n\ \❰x❱: \n\ \ \n\ \ \n\ \ ┌─────────────────┐ \n\ \ │ λ(x : Bool) → x │ Anonymous functions introduce “bound” variables \n\ \ └─────────────────┘ \n\ \ ⇧ \n\ \ This is the bound variable \n\ \ \n\ \ \n\ \ ┌─────────────────┐ \n\ \ │ let x = 1 in x │ ❰let❱ expressions introduce “bound” variables \n\ \ └─────────────────┘ \n\ \ ⇧ \n\ \ This is the bound variable \n\ \ \n\ \ \n\ \However, the following expressions are not valid because they all reference a \n\ \variable that has not been introduced yet (i.e. an “unbound” variable): \n\ \ \n\ \ \n\ \ ┌─────────────────┐ \n\ \ │ λ(x : Bool) → y │ The variable ❰y❱ hasn't been introduced yet \n\ \ └─────────────────┘ \n\ \ ⇧ \n\ \ This is the unbound variable \n\ \ \n\ \ \n\ \ ┌──────────────────────────┐ \n\ \ │ (let x = True in x) && x │ ❰x❱ is undefined outside the parentheses \n\ \ └──────────────────────────┘ \n\ \ ⇧ \n\ \ This is the unbound variable \n\ \ \n\ \ \n\ \ ┌────────────────┐ \n\ \ │ let x = x in x │ The definition for ❰x❱ cannot reference itself \n\ \ └────────────────┘ \n\ \ ⇧ \n\ \ This is the unbound variable \n\ \ \n\ \ \n\ \Some common reasons why you might get this error: \n\ \ \n\ \● You misspell a variable name, like this: \n\ \ \n\ \ \n\ \ ┌────────────────────────────────────────────────────┐ \n\ \ │ λ(empty : Bool) → if emty then \"Empty\" else \"Full\" │ \n\ \ └────────────────────────────────────────────────────┘ \n\ \ ⇧ \n\ \ Typo \n\ \ \n\ \ \n\ \● You misspell a reserved identifier, like this: \n\ \ \n\ \ \n\ \ ┌──────────────────────────┐ \n\ \ │ foral (a : Type) → a → a │ \n\ \ └──────────────────────────┘ \n\ \ ⇧ \n\ \ Typo \n\ \ \n\ \ \n\ \● You tried to define a recursive value, like this: \n\ \ \n\ \ \n\ \ ┌────────────────────┐ \n\ \ │ let x = x + 1 in x │ \n\ \ └────────────────────┘ \n\ \ ⇧ \n\ \ Recursive definitions are not allowed \n\ \ \n\ \ \n\ \● You accidentally forgot a ❰λ❱ or ❰∀❱/❰forall❱ \n\ \ \n\ \ \n\ \ Unbound variable \n\ \ ⇩ \n\ \ ┌─────────────────┐ \n\ \ │ (x : Bool) → x │ \n\ \ └─────────────────┘ \n\ \ ⇧ \n\ \ A ❰λ❱ here would transform this into a valid anonymous function \n\ \ \n\ \ \n\ \ Unbound variable \n\ \ ⇩ \n\ \ ┌────────────────────┐ \n\ \ │ (x : Bool) → Bool │ \n\ \ └────────────────────┘ \n\ \ ⇧ \n\ \ A ❰∀❱ or ❰forall❱ here would transform this into a valid function type \n\ \ \n\ \ \n\ \● You forgot to prefix a file path with ❰./❱: \n\ \ \n\ \ \n\ \ ┌────────────────────┐ \n\ \ │ path/to/file.dhall │ \n\ \ └────────────────────┘ \n\ \ ⇧ \n\ \ This should be ❰./path/to/file.dhall❱ \n" prettyTypeMessage (InvalidInputType expr) = ErrorMessages {..} where short = "Invalid function input" long = "Explanation: A function can accept an input “term” that has a given “type”, like\n\ \this: \n\ \ \n\ \ \n\ \ This is the input term that the function accepts \n\ \ ⇩ \n\ \ ┌───────────────────────┐ \n\ \ │ ∀(x : Natural) → Bool │ This is the type of a function that accepts an \n\ \ └───────────────────────┘ input term named ❰x❱ that has type ❰Natural❱ \n\ \ ⇧ \n\ \ This is the type of the input term \n\ \ \n\ \ \n\ \ ┌────────────────┐ \n\ \ │ Bool → Natural │ This is the type of a function that accepts an anonymous\n\ \ └────────────────┘ input term that has type ❰Bool❱ \n\ \ ⇧ \n\ \ This is the type of the input term \n\ \ \n\ \ \n\ \... or a function can accept an input “type” that has a given “kind”, like this:\n\ \ \n\ \ \n\ \ This is the input type that the function accepts \n\ \ ⇩ \n\ \ ┌────────────────────┐ \n\ \ │ ∀(a : Type) → Type │ This is the type of a function that accepts an input\n\ \ └────────────────────┘ type named ❰a❱ that has kind ❰Type❱ \n\ \ ⇧ \n\ \ This is the kind of the input type \n\ \ \n\ \ \n\ \ ┌──────────────────────┐ \n\ \ │ (Type → Type) → Type │ This is the type of a function that accepts an \n\ \ └──────────────────────┘ anonymous input type that has kind ❰Type → Type❱ \n\ \ ⇧ \n\ \ This is the kind of the input type \n\ \ \n\ \ \n\ \Other function inputs are " <> _NOT <> " valid, like this: \n\ \ \n\ \ \n\ \ ┌──────────────┐ \n\ \ │ ∀(x : 1) → x │ ❰1❱ is a “term” and not a “type” nor a “kind” so ❰x❱ \n\ \ └──────────────┘ cannot have “type” ❰1❱ or “kind” ❰1❱ \n\ \ ⇧ \n\ \ This is not a type or kind \n\ \ \n\ \ \n\ \ ┌──────────┐ \n\ \ │ True → x │ ❰True❱ is a “term” and not a “type” nor a “kind” so the \n\ \ └──────────┘ anonymous input cannot have “type” ❰True❱ or “kind” ❰True❱ \n\ \ ⇧ \n\ \ This is not a type or kind \n\ \ \n\ \ \n\ \You annotated a function input with the following expression: \n\ \ \n\ \" <> txt <> "\n\ \ \n\ \... which is neither a type nor a kind \n" where txt = insert expr prettyTypeMessage (InvalidOutputType expr) = ErrorMessages {..} where short = "Invalid function output" long = "Explanation: A function can return an output “term” that has a given “type”, \n\ \like this: \n\ \ \n\ \ \n\ \ ┌────────────────────┐ \n\ \ │ ∀(x : Text) → Bool │ This is the type of a function that returns an \n\ \ └────────────────────┘ output term that has type ❰Bool❱ \n\ \ ⇧ \n\ \ This is the type of the output term \n\ \ \n\ \ \n\ \ ┌────────────────┐ \n\ \ │ Bool → Natural │ This is the type of a function that returns an output \n\ \ └────────────────┘ term that has type ❰Natural❱ \n\ \ ⇧ \n\ \ This is the type of the output term \n\ \ \n\ \ \n\ \... or a function can return an output “type” that has a given “kind”, like \n\ \this: \n\ \ \n\ \ ┌────────────────────┐ \n\ \ │ ∀(a : Type) → Type │ This is the type of a function that returns an \n\ \ └────────────────────┘ output type that has kind ❰Type❱ \n\ \ ⇧ \n\ \ This is the kind of the output type \n\ \ \n\ \ \n\ \ ┌──────────────────────┐ \n\ \ │ (Type → Type) → Type │ This is the type of a function that returns an \n\ \ └──────────────────────┘ output type that has kind ❰Type❱ \n\ \ ⇧ \n\ \ This is the kind of the output type \n\ \ \n\ \ \n\ \Other outputs are " <> _NOT <> " valid, like this: \n\ \ \n\ \ \n\ \ ┌─────────────────┐ \n\ \ │ ∀(x : Bool) → x │ ❰x❱ is a “term” and not a “type” nor a “kind” so the \n\ \ └─────────────────┘ output cannot have “type” ❰x❱ or “kind” ❰x❱ \n\ \ ⇧ \n\ \ This is not a type or kind \n\ \ \n\ \ \n\ \ ┌─────────────┐ \n\ \ │ Text → True │ ❰True❱ is a “term” and not a “type” nor a “kind” so the \n\ \ └─────────────┘ output cannot have “type” ❰True❱ or “kind” ❰True❱ \n\ \ ⇧ \n\ \ This is not a type or kind \n\ \ \n\ \ \n\ \Some common reasons why you might get this error: \n\ \ \n\ \● You use ❰∀❱ instead of ❰λ❱ by mistake, like this: \n\ \ \n\ \ \n\ \ ┌────────────────┐ \n\ \ │ ∀(x: Bool) → x │ \n\ \ └────────────────┘ \n\ \ ⇧ \n\ \ Using ❰λ❱ here instead of ❰∀❱ would transform this into a valid function \n\ \ \n\ \ \n\ \────────────────────────────────────────────────────────────────────────────────\n\ \ \n\ \You specified that your function outputs a: \n\ \ \n\ \" <> txt <> "\n\ \ \n\ \... which is neither a type nor a kind: \n" where txt = insert expr prettyTypeMessage (NotAFunction expr0 expr1) = ErrorMessages {..} where short = "Not a function" long = "Explanation: Expressions separated by whitespace denote function application, \n\ \like this: \n\ \ \n\ \ \n\ \ ┌─────┐ \n\ \ │ f x │ This denotes the function ❰f❱ applied to an argument named ❰x❱ \n\ \ └─────┘ \n\ \ \n\ \ \n\ \A function is a term that has type ❰a → b❱ for some ❰a❱ or ❰b❱. For example, \n\ \the following expressions are all functions because they have a function type: \n\ \ \n\ \ \n\ \ The function's input type is ❰Bool❱ \n\ \ ⇩ \n\ \ ┌───────────────────────────────┐ \n\ \ │ λ(x : Bool) → x : Bool → Bool │ User-defined anonymous function \n\ \ └───────────────────────────────┘ \n\ \ ⇧ \n\ \ The function's output type is ❰Bool❱ \n\ \ \n\ \ \n\ \ The function's input type is ❰Natural❱ \n\ \ ⇩ \n\ \ ┌───────────────────────────────┐ \n\ \ │ Natural/even : Natural → Bool │ Built-in function \n\ \ └───────────────────────────────┘ \n\ \ ⇧ \n\ \ The function's output type is ❰Bool❱ \n\ \ \n\ \ \n\ \ The function's input kind is ❰Type❱ \n\ \ ⇩ \n\ \ ┌───────────────────────────────┐ \n\ \ │ λ(a : Type) → a : Type → Type │ Type-level functions are still functions \n\ \ └───────────────────────────────┘ \n\ \ ⇧ \n\ \ The function's output kind is ❰Type❱ \n\ \ \n\ \ \n\ \ The function's input kind is ❰Type❱ \n\ \ ⇩ \n\ \ ┌────────────────────┐ \n\ \ │ List : Type → Type │ Built-in type-level function \n\ \ └────────────────────┘ \n\ \ ⇧ \n\ \ The function's output kind is ❰Type❱ \n\ \ \n\ \ \n\ \ Function's input has kind ❰Type❱ \n\ \ ⇩ \n\ \ ┌─────────────────────────────────────────────────┐ \n\ \ │ List/head : ∀(a : Type) → (List a → Optional a) │ A function can return \n\ \ └─────────────────────────────────────────────────┘ another function \n\ \ ⇧ \n\ \ Function's output has type ❰List a → Optional a❱\n\ \ \n\ \ \n\ \ The function's input type is ❰List Text❱ \n\ \ ⇩ \n\ \ ┌────────────────────────────────────────────┐ \n\ \ │ List/head Text : List Text → Optional Text │ A function applied to an \n\ \ └────────────────────────────────────────────┘ argument can be a function \n\ \ ⇧ \n\ \ The function's output type is ❰Optional Text❱\n\ \ \n\ \ \n\ \An expression is not a function if the expression's type is not of the form \n\ \❰a → b❱. For example, these are " <> _NOT <> " functions: \n\ \ \n\ \ \n\ \ ┌─────────────┐ \n\ \ │ 1 : Natural │ ❰1❱ is not a function because ❰Natural❱ is not the type of \n\ \ └─────────────┘ a function \n\ \ \n\ \ \n\ \ ┌───────────────────────┐ \n\ \ │ Natural/even 2 : Bool │ ❰Natural/even 2❱ is not a function because \n\ \ └───────────────────────┘ ❰Bool❱ is not the type of a function \n\ \ \n\ \ \n\ \ ┌──────────────────┐ \n\ \ │ List Text : Type │ ❰List Text❱ is not a function because ❰Type❱ is not \n\ \ └──────────────────┘ the type of a function \n\ \ \n\ \ \n\ \Some common reasons why you might get this error: \n\ \ \n\ \● You tried to add two ❰Natural❱s without a space around the ❰+❱, like this: \n\ \ \n\ \ \n\ \ ┌─────┐ \n\ \ │ 2+2 │ \n\ \ └─────┘ \n\ \ \n\ \ \n\ \ The above code is parsed as: \n\ \ \n\ \ \n\ \ ┌────────┐ \n\ \ │ 2 (+2) │ \n\ \ └────────┘ \n\ \ ⇧ \n\ \ The compiler thinks that this ❰2❱ is a function whose argument is ❰+2❱ \n\ \ \n\ \ \n\ \ This is because the ❰+❱ symbol has two meanings: you use ❰+❱ to add two \n\ \ numbers, but you also can prefix ❰Natural❱ literals with a ❰+❱ to turn them \n\ \ into ❰Integer❱ literals (like ❰+2❱) \n\ \ \n\ \ To fix the code, you need to put spaces around the ❰+❱, like this: \n\ \ \n\ \ \n\ \ ┌───────┐ \n\ \ │ 2 + 2 │ \n\ \ └───────┘ \n\ \ \n\ \ \n\ \────────────────────────────────────────────────────────────────────────────────\n\ \ \n\ \You tried to use the following expression as a function: \n\ \ \n\ \" <> txt0 <> "\n\ \ \n\ \... but this expression's type is: \n\ \ \n\ \" <> txt1 <> "\n\ \ \n\ \... which is not a function type \n" where txt0 = insert expr0 txt1 = insert expr1 prettyTypeMessage (TypeMismatch expr0 expr1 expr2 expr3) = ErrorMessages {..} where short = "Wrong type of function argument\n" <> "\n" <> 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" long = "Explanation: Every union literal begins by selecting one alternative and \n\ \specifying the value for that alternative, like this: \n\ \ \n\ \ \n\ \ Select the ❰Left❱ alternative, whose value is ❰True❱ \n\ \ ⇩ \n\ \ ┌──────────────────────────────────┐ \n\ \ │ < Left = True, Right : Natural > │ A union literal with two alternatives \n\ \ └──────────────────────────────────┘ \n\ \ \n\ \ \n\ \However, this value must be a term and not a type. For example, the following \n\ \values are " <> _NOT <> " valid: \n\ \ \n\ \ \n\ \ ┌──────────────────────────────────┐ \n\ \ │ < Left = Text, Right : Natural > │ Invalid union literal \n\ \ └──────────────────────────────────┘ \n\ \ ⇧ \n\ \ This is a type and not a term \n\ \ \n\ \ \n\ \ ┌───────────────────────────────┐ \n\ \ │ < Left = Type, Right : Type > │ Invalid union type \n\ \ └───────────────────────────────┘ \n\ \ ⇧ \n\ \ This is a kind and not a term \n\ \ \n\ \ \n\ \Some common reasons why you might get this error: \n\ \ \n\ \● You accidentally typed ❰=❱ instead of ❰:❱ for a union literal with one \n\ \ alternative: \n\ \ \n\ \ \n\ \ ┌────────────────────┐ \n\ \ │ < Example = Text > │ \n\ \ └────────────────────┘ \n\ \ ⇧ \n\ \ This could be ❰:❱ instead \n\ \ \n\ \ \n\ \────────────────────────────────────────────────────────────────────────────────\n\ \ \n\ \You provided a union literal with an alternative named: \n\ \ \n\ \" <> txt0 <> "\n\ \ \n\ \... whose value is: \n\ \ \n\ \" <> txt1 <> "\n\ \ \n\ \... which is not a term \n" where txt0 = insert k txt1 = insert expr0 prettyTypeMessage (InvalidAlternative k expr0) = ErrorMessages {..} where short = "Invalid alternative" long = "Explanation: Every union type specifies the type of each alternative, like this:\n\ \ \n\ \ \n\ \ The type of the first alternative is ❰Bool❱ \n\ \ ⇩ \n\ \ ┌──────────────────────────────────┐ \n\ \ │ < Left : Bool, Right : Natural > │ A union type with two alternatives \n\ \ └──────────────────────────────────┘ \n\ \ ⇧ \n\ \ The type of the second alternative is ❰Natural❱ \n\ \ \n\ \ \n\ \However, these alternatives can only be annotated with types. For example, the \n\ \following union types are " <> _NOT <> " valid: \n\ \ \n\ \ \n\ \ ┌────────────────────────────┐ \n\ \ │ < Left : Bool, Right : 1 > │ Invalid union type \n\ \ └────────────────────────────┘ \n\ \ ⇧ \n\ \ This is a term and not a type \n\ \ \n\ \ \n\ \ ┌───────────────────────────────┐ \n\ \ │ < Left : Bool, Right : Type > │ Invalid union type \n\ \ └───────────────────────────────┘ \n\ \ ⇧ \n\ \ This is a kind and not a type \n\ \ \n\ \ \n\ \Some common reasons why you might get this error: \n\ \ \n\ \● You accidentally typed ❰:❱ instead of ❰=❱ for a union literal with one \n\ \ alternative: \n\ \ \n\ \ ┌─────────────────┐ \n\ \ │ < Example : 1 > │ \n\ \ └─────────────────┘ \n\ \ ⇧ \n\ \ This could be ❰=❱ instead \n\ \ \n\ \ \n\ \────────────────────────────────────────────────────────────────────────────────\n\ \ \n\ \You provided a union type with an alternative named: \n\ \ \n\ \" <> txt0 <> "\n\ \ \n\ \... annotated with the following expression which is not a type: \n\ \ \n\ \" <> txt1 <> "\n" where txt0 = insert k txt1 = insert expr0 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 (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) => Show (TypeError s a) where show = Pretty.renderString . Pretty.layoutPretty layoutOpts . Pretty.pretty 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 (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) => Show (DetailedTypeError s a) where show = Pretty.renderString . Pretty.layoutPretty layoutOpts . Pretty.pretty 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 (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 () dhall-1.19.1/src/Dhall/Util.hs0000644000000000000000000000340113377175666014164 0ustar0000000000000000{-# LANGUAGE OverloadedStrings #-} -- | Shared utility functions module Dhall.Util ( snip , snipDoc ) where import Data.Monoid ((<>)) import Data.Text (Text) import Data.Text.Prettyprint.Doc (Doc) import Dhall.Pretty (Ann) import qualified Data.Text import qualified Data.Text.Prettyprint.Doc as Pretty import qualified Data.Text.Prettyprint.Doc.Render.Text as Pretty import qualified Dhall.Pretty -- | Utility function to cut out the interior of a large text block snip :: Text -> Text snip text | length ls <= 7 = text | otherwise = if Data.Text.last text == '\n' then preview else Data.Text.init preview where ls = Data.Text.lines text header = take 3 ls footer = takeEnd 3 ls excerpt = filter (Data.Text.any (/= ' ')) (header <> footer) leadingSpaces = Data.Text.length . Data.Text.takeWhile (== ' ') minSpaces = minimum (map leadingSpaces excerpt) maxLength = maximum (map Data.Text.length excerpt) separator = Data.Text.replicate minSpaces " " <> Data.Text.replicate (maxLength - minSpaces) "=" preview = Data.Text.unlines header <> separator <> "\n" <> Data.Text.unlines footer {-| Like `snip`, but for `Doc`s Note that this has to be opinionated and render ANSI color codes, but that should be fine because we don't use this in a non-interactive context -} snipDoc :: Doc Ann -> Doc a snipDoc doc = Pretty.align (Pretty.pretty (snip text)) where stream = Pretty.layoutSmart Dhall.Pretty.layoutOpts doc ansiStream = fmap Dhall.Pretty.annToAnsiStyle stream text = Pretty.renderStrict ansiStream takeEnd :: Int -> [a] -> [a] takeEnd n l = go (drop n l) l where go (_:xs) (_:ys) = go xs ys go _ r = r dhall-1.19.1/src/Dhall/Import/0000755000000000000000000000000013377175666014167 5ustar0000000000000000dhall-1.19.1/src/Dhall/Import/HTTP.hs0000644000000000000000000001046313377175666015306 0ustar0000000000000000{-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} module Dhall.Import.HTTP where 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 Lens.Family.State.Strict (zoom) import qualified Control.Exception import qualified Control.Monad.Trans.State.Strict as State import qualified Data.Text as Text import qualified Data.Text.Lazy import qualified Data.Text.Lazy.Encoding import Dhall.Import.Types #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 <> "\n" ResponseTimeout -> "\n" <> "\ESC[1;31mError\ESC[0m: The remote host took too long to respond\n" StatusCodeException response _ | statusCode == 404 -> "\n" <> "\ESC[1;31mError\ESC[0m: Remote file not found\n" | otherwise -> "\n" <> "\ESC[1;31mError\ESC[0m: Unexpected HTTP status code:\n" <> "\n" <> "↳ " <> show statusCode <> "\n" 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 fetchFromHttpUrl :: String -> Maybe [(CI ByteString, ByteString)] -> StateT (Status m) IO (String, Text.Text) fetchFromHttpUrl url mheaders = do m <- needManager request <- liftIO (HTTP.parseUrlThrow url) 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) let bytes = HTTP.responseBody response case Data.Text.Lazy.Encoding.decodeUtf8' bytes of Left err -> liftIO (Control.Exception.throwIO err) Right text -> return (url, Data.Text.Lazy.toStrict text) dhall-1.19.1/src/Dhall/Import/Types.hs0000644000000000000000000001524613377175666015637 0ustar0000000000000000{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} {-# OPTIONS_GHC -Wall #-} module Dhall.Import.Types where import Control.Exception (Exception) import Control.Monad.Trans.State.Strict (StateT) import Data.Dynamic import Data.List.NonEmpty (NonEmpty) import Data.Map (Map) import Data.Semigroup ((<>)) import Dhall.Binary (StandardVersion(..)) 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) import qualified Dhall.Binary import qualified Dhall.Context import qualified Data.Map as Map import qualified Data.Text -- | State threaded throughout the import process data Status m = Status { _stack :: NonEmpty Import -- ^ 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 , _cache :: Map Import (NodeId, Expr Src X) -- ^ 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 , _standardVersion :: StandardVersion , _normalizer :: ReifiedNormalizer X , _startingContext :: Context (Expr Src X) , _resolver :: Import -> StateT (Status m) m (Expr Src Import) , _cacher :: Import -> Expr Src X -> StateT (Status m) m () } -- | Default starting `Status` that is polymorphic in the base `Monad` emptyStatusWith :: (Import -> StateT (Status m) m (Expr Src Import)) -> (Import -> Expr Src X -> StateT (Status m) m ()) -> FilePath -> Status m emptyStatusWith _resolver _cacher rootDirectory = Status {..} where _stack = pure rootImport _dot = importNode (userNodeId 0) rootImport _nextNodeId = 1 _cache = Map.empty _manager = Nothing _standardVersion = Dhall.Binary.defaultStandardVersion _normalizer = ReifiedNormalizer (const (pure 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 stack :: Functor f => LensLike' f (Status m) (NonEmpty Import) stack k s = fmap (\x -> s { _stack = x }) (k (_stack s)) dot :: Functor f => LensLike' f (Status m) (Dot NodeId) dot k s = fmap (\x -> s { _dot = x }) (k (_dot s)) nextNodeId :: Functor f => LensLike' f (Status m) Int nextNodeId k s = fmap (\x -> s { _nextNodeId = x }) (k (_nextNodeId s)) cache :: Functor f => LensLike' f (Status m) (Map Import (NodeId, Expr Src X)) cache k s = fmap (\x -> s { _cache = x }) (k (_cache s)) manager :: Functor f => LensLike' f (Status m) (Maybe Dynamic) manager k s = fmap (\x -> s { _manager = x }) (k (_manager s)) standardVersion :: Functor f => LensLike' f (Status m) StandardVersion standardVersion k s = fmap (\x -> s { _standardVersion = x }) (k (_standardVersion s)) normalizer :: Functor f => LensLike' f (Status m) (ReifiedNormalizer X) normalizer k s = fmap (\x -> s { _normalizer = x }) (k (_normalizer s)) startingContext :: Functor f => LensLike' f (Status m) (Context (Expr Src X)) startingContext k s = fmap (\x -> s { _startingContext = x }) (k (_startingContext s)) resolver :: Functor f => LensLike' f (Status m) (Import -> StateT (Status m) m (Expr Src Import)) resolver k s = fmap (\x -> s { _resolver = x }) (k (_resolver s)) 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)) {-| This exception indicates that there was an internal error in Dhall's import-related logic the `expected` type then the `extract` function must succeed. If not, then this exception is thrown This exception indicates that an invalid `Type` was provided to the `input` function -} data InternalError = InternalError deriving (Typeable) instance Show InternalError where show InternalError = unlines [ _ERROR <> ": Compiler bug " , " " , "Explanation: This error message means that there is a bug in the Dhall compiler." , "You didn't do anything wrong, but if you would like to see this problem fixed " , "then you should report the bug at: " , " " , "https://github.com/dhall-lang/dhall-haskell/issues " , " " , "Please include the following text in your bug report: " , " " , "``` " , "Header extraction failed even though the header type-checked " , "``` " ] where _ERROR :: String _ERROR = "\ESC[1;31mError\ESC[0m" instance Exception InternalError -- | Wrapper around `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' data PrettyHttpException = PrettyHttpException String Dynamic deriving (Typeable) instance Exception PrettyHttpException instance Show PrettyHttpException where show (PrettyHttpException msg _) = msg dhall-1.19.1/src/Dhall/Parser/0000755000000000000000000000000013377175666014151 5ustar0000000000000000dhall-1.19.1/src/Dhall/Parser/Combinators.hs0000644000000000000000000001770213377175666016774 0ustar0000000000000000{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE OverloadedStrings #-} module Dhall.Parser.Combinators where import Control.Applicative (Alternative (..), liftA2) import Control.Monad (MonadPlus (..)) import Data.Data (Data) 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 Prelude hiding (const, pi) 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.Text import qualified Dhall.Map import qualified Dhall.Util import qualified Dhall.Set import qualified Text.Megaparsec import qualified Text.Megaparsec.Char import qualified Text.Parser.Char import qualified Text.Parser.Combinators import qualified Text.Parser.Token.Style -- | Source code extract data Src = Src !Text.Megaparsec.SourcePos !Text.Megaparsec.SourcePos Text -- Text field is intentionally lazy deriving (Data, Eq, Show) -- | Doesn't force the 'Text' part laxSrcEq :: Src -> Src -> Bool laxSrcEq (Src p q _) (Src p' q' _) = eq p p' && eq q q' where -- Don't compare filename (which is FilePath = String) eq :: Text.Megaparsec.SourcePos -> Text.Megaparsec.SourcePos -> Bool eq (Text.Megaparsec.SourcePos _ a b) (Text.Megaparsec.SourcePos _ a' b') = a == a' && b == b' {-# INLINE laxSrcEq #-} instance Pretty Src where pretty (Src begin _ text) = pretty (Dhall.Util.snip (prefix <> text)) <> "\n" <> pretty (Text.Megaparsec.sourcePosPretty begin) where prefix = Data.Text.replicate (n - 1) " " where n = Text.Megaparsec.unPos (Text.Megaparsec.sourceColumn begin) {-| A `Parser` that is almost identical to @"Text.Megaparsec".`Text.Megaparsec.Parsec`@ except treating Haskell-style comments as whitespace -} newtype Parser a = Parser { unParser :: Text.Megaparsec.Parsec Void Text a } instance Functor Parser where fmap f (Parser x) = Parser (fmap f x) {-# INLINE fmap #-} f <$ Parser x = Parser (f <$ x) {-# INLINE (<$) #-} instance Applicative Parser where pure = Parser . pure {-# INLINE pure #-} Parser f <*> Parser x = Parser (f <*> x) {-# INLINE (<*>) #-} Parser a <* Parser b = Parser (a <* b) {-# INLINE (<*) #-} Parser a *> Parser b = Parser (a *> b) {-# INLINE (*>) #-} instance Monad Parser where return = pure {-# INLINE return #-} (>>) = (*>) {-# INLINE (>>) #-} Parser n >>= k = Parser (n >>= unParser . k) {-# INLINE (>>=) #-} fail = Control.Monad.Fail.fail {-# INLINE fail #-} instance Control.Monad.Fail.MonadFail Parser where fail = Parser . Control.Monad.Fail.fail {-# INLINE fail #-} instance Alternative Parser where empty = Parser empty -- {-# INLINE empty #-} Parser a <|> Parser b = Parser (a <|> b) -- {-# INLINE (<|>) #-} some (Parser a) = Parser (some a) -- {-# INLINE some #-} many (Parser a) = Parser (many a) -- {-# INLINE many #-} instance MonadPlus Parser where mzero = empty -- {-# INLINE mzero #-} mplus = (<|>) -- {-# INLINE mplus #-} instance Text.Megaparsec.MonadParsec Void Text Parser where failure u e = Parser (Text.Megaparsec.failure u e) fancyFailure e = Parser (Text.Megaparsec.fancyFailure e) label l (Parser p) = Parser (Text.Megaparsec.label l p) hidden (Parser p) = Parser (Text.Megaparsec.hidden p) try (Parser p) = Parser (Text.Megaparsec.try p) lookAhead (Parser p) = Parser (Text.Megaparsec.lookAhead p) notFollowedBy (Parser p) = Parser (Text.Megaparsec.notFollowedBy p) withRecovery e (Parser p) = Parser (Text.Megaparsec.withRecovery (unParser . e) p) observing (Parser p) = Parser (Text.Megaparsec.observing p) eof = Parser Text.Megaparsec.eof token f e = Parser (Text.Megaparsec.token f e) tokens f ts = Parser (Text.Megaparsec.tokens f ts) takeWhileP s f = Parser (Text.Megaparsec.takeWhileP s f) takeWhile1P s f = Parser (Text.Megaparsec.takeWhile1P s f) takeP s n = Parser (Text.Megaparsec.takeP s n) getParserState = Parser Text.Megaparsec.getParserState {-# INLINE getParserState #-} updateParserState f = Parser (Text.Megaparsec.updateParserState f) instance Data.Semigroup.Semigroup a => Data.Semigroup.Semigroup (Parser a) where (<>) = liftA2 (<>) instance (Data.Semigroup.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) instance Text.Parser.Combinators.Parsing Parser where try = Text.Megaparsec.try () = (Text.Megaparsec.) skipMany = Text.Megaparsec.skipMany skipSome = Text.Megaparsec.skipSome unexpected = fail eof = Parser Text.Megaparsec.eof notFollowedBy = Text.Megaparsec.notFollowedBy instance Text.Parser.Char.CharParsing Parser where satisfy = Parser . Text.Megaparsec.satisfy char = Text.Megaparsec.Char.char notChar = Text.Megaparsec.Char.char anyChar = Text.Megaparsec.anySingle string = fmap Data.Text.unpack . Text.Megaparsec.Char.string . fromString text = Text.Megaparsec.Char.string instance TokenParsing Parser where someSpace = Text.Parser.Token.Style.buildSomeSpaceParser (Parser (Text.Megaparsec.skipSome (Text.Megaparsec.satisfy Data.Char.isSpace))) Text.Parser.Token.Style.haskellCommentStyle highlight _ = id semi = token (Text.Megaparsec.Char.char ';' ";") count :: (Semigroup a, Monoid a) => Int -> Parser a -> Parser a count n parser = mconcat (replicate n parser) range :: (Semigroup a, Monoid a) => Int -> Int -> Parser a -> Parser a range minimumBound maximumMatches parser = count minimumBound parser <> loop maximumMatches where loop 0 = mempty loop n = (parser <> loop (n - 1)) <|> mempty option :: (Alternative f, Monoid a) => f a -> f a option p = p <|> pure mempty star :: (Alternative f, Monoid a) => f a -> f a star p = plus p <|> pure mempty plus :: (Alternative f, Monoid a) => f a -> f a plus p = mappend <$> p <*> star p satisfy :: (Char -> Bool) -> Parser Text satisfy = fmap Data.Text.singleton . Text.Parser.Char.satisfy takeWhile :: (Char -> Bool) -> Parser Text takeWhile predicate = Parser (Text.Megaparsec.takeWhileP Nothing predicate) takeWhile1 :: (Char -> Bool) -> Parser Text takeWhile1 predicate = Parser (Text.Megaparsec.takeWhile1P Nothing predicate) noDuplicates :: Ord a => [a] -> Parser (Set a) noDuplicates = go Dhall.Set.empty where go found [] = return found go found (x:xs) = if Data.Set.member x (Dhall.Set.toSet found) then fail "Duplicate key" else go (Dhall.Set.append x found) xs 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 ("duplicate field: " ++ Data.Text.unpack k) Dhall.Map.traverseWithKey action m where fromListWith combine = foldr cons mempty where cons (k, v) = Dhall.Map.insertWith combine k v dhall-1.19.1/src/Dhall/Parser/Expression.hs0000644000000000000000000006051113377175666016647 0ustar0000000000000000{-# 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.Semigroup (Semigroup(..)) import Data.Text (Text) import Dhall.Core 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.List.NonEmpty import qualified Data.Sequence import qualified Data.Text import qualified Data.Text.Encoding import qualified Text.Megaparsec import qualified Text.Parser.Char import Dhall.Parser.Combinators import Dhall.Parser.Token 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) 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 -> return (ListLit (Just c) xs) 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 <|> BoolNE <$ _notEqual precedence3Operator = BoolEQ <$ _doubleEqual precedence0Expression = makeOperatorExpression precedence1Expression precedence0Operator precedence1Expression = makeOperatorExpression precedence2Expression precedence1Operator precedence2Expression = makeOperatorExpression precedence3Expression precedence2Operator precedence3Expression = makeOperatorExpression applicationExpression precedence3Operator applicationExpression = do f <- (do _constructors; return Constructors) <|> (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 left x e = Field e x let right xs e = Project e xs b <- Text.Megaparsec.many (try (do _dot; fmap left label <|> fmap right labels)) 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 <- Text.Megaparsec.getOffset a <- try doubleLiteral b <- if isInfinite a then Text.Megaparsec.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 [ 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.Megaparsec.single '$' 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 "''" -- This is technically not in the grammar, but it's still equivalent to the -- original grammar and an easy way to discard the first character if it's -- a newline _ <- optional endOfLine a <- singleQuoteContinue return (dedent 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 <- label let nonEmptyRecordType = do _colon b <- expression e <- Text.Megaparsec.many (do _comma c <- label _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 <- label _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 <- label let alternative0 = do _equal b <- expression kvs <- Text.Megaparsec.many (do _bar c <- label _colon d <- expression return (c, d) ) return (UnionLit a b, kvs) let alternative1 = do _colon b <- 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 (Directory segments) final <- file_ return (Local Here (File (Directory (segments ++ [".."])) final)) herePath = do _ <- "." :: Parser Text file <- file_ return (Local Here file) homePath = do _ <- "~" :: Parser Text file <- file_ return (Local Home file) absolutePath = do file <- file_ 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 (importHashed_ <|> (_openParens *> importHashed_ <* _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}" dedent :: Chunks Src a -> Chunks Src a dedent chunks0 = process chunks0 where text0 = renderChunks chunks0 lines0 = Data.Text.lines text0 isEmpty = Data.Text.all Data.Char.isSpace nonEmptyLines = filter (not . isEmpty) lines0 indentLength line = Data.Text.length (Data.Text.takeWhile Data.Char.isSpace line) shortestIndent = case nonEmptyLines of [] -> 0 _ -> minimum (map indentLength nonEmptyLines) -- The purpose of this complicated `trimBegin`/`trimContinue` is to ensure -- that we strip leading whitespace without stripping whitespace after -- variable interpolation -- This is the trim function we use up until the first variable -- interpolation, dedenting all lines trimBegin = Data.Text.intercalate "\n" . map (Data.Text.drop shortestIndent) . Data.Text.splitOn "\n" -- This is the trim function we use after each variable interpolation -- where we indent each line except the first line (since it's not a true -- beginning of a line) trimContinue text = Data.Text.intercalate "\n" lines_ where lines_ = case Data.Text.splitOn "\n" text of [] -> [] l:ls -> l:map (Data.Text.drop shortestIndent) ls -- This is the loop that drives whether or not to use `trimBegin` or -- `trimContinue`. We call this function with `trimBegin`, but after the -- first interpolation we switch permanently to `trimContinue` process (Chunks ((x0, y0):xys) z) = Chunks ((trimBegin x0, y0):xys') (trimContinue z) where xys' = [ (trimContinue x, y) | (x, y) <- xys ] process (Chunks [] z) = Chunks [] (trimBegin z) dhall-1.19.1/src/Dhall/Parser/Token.hs0000644000000000000000000004156513377175666015600 0ustar0000000000000000{-# 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, file_, label, 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, _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 Text.Megaparsec 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.Parser.Token.natural return (sign a) ) "integer literal" naturalLiteral :: Parser Natural naturalLiteral = (do a <- Text.Parser.Token.natural return (fromIntegral a) ) "natural literal" identifier :: Parser Var identifier = do x <- label let indexed = do _ <- Text.Parser.Char.char '@' Text.Parser.Token.natural n <- indexed <|> pure 0 return (V x n) 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 :: Parser Text simpleLabel = try (do c <- Text.Parser.Char.satisfy headCharacter rest <- Dhall.Parser.Combinators.takeWhile tailCharacter let text = Data.Text.cons c rest Control.Monad.guard (not (Data.HashSet.member text reservedIdentifiers)) return text ) where headCharacter c = alpha c || c == '_' tailCharacter c = alpha c || digit c || c == '_' || c == '-' || c == '/' backtickLabel :: Parser Text backtickLabel = do _ <- Text.Parser.Char.char '`' t <- takeWhile1 predicate _ <- Text.Parser.Char.char '`' return t where predicate c = alpha c || digit c || elem c ("$-/_:." :: String) labels :: Parser (Set Text) labels = do _openBrace xs <- nonEmptyLabels <|> emptyLabels _closeBrace return xs where emptyLabels = pure Dhall.Set.empty nonEmptyLabels = do x <- label xs <- many (do _ <- _comma; label) noDuplicates (x : xs) label :: Parser Text label = (do t <- backtickLabel <|> simpleLabel whitespace return t ) "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 = ("\\" <> satisfy predicate0) <|> satisfy predicate1 where predicate0 c = c `elem` ("\"\\abfnrtv" :: String) predicate1 c = ('\x20' <= c && c <= '\x21') || ('\x23' <= c && c <= '\x3C') || ('\x3E' <= c && c <= '\x5B') || ('\x5D' <= c && c <= '\x7E') quotedPathCharacter :: Char -> Bool quotedPathCharacter c = ('\x20' <= c && c <= '\x21') || ('\x23' <= c && c <= '\x2E') || ('\x30' <= c && c <= '\x7E') pathComponent :: Parser Text pathComponent = do _ <- "/" :: Parser Text let pathData = Text.Megaparsec.takeWhile1P Nothing Dhall.Core.pathCharacter let quotedPathData = do _ <- Text.Parser.Char.char '"' text <- Text.Megaparsec.takeWhile1P Nothing quotedPathCharacter _ <- Text.Parser.Char.char '"' return text pathData <|> quotedPathData file_ :: Parser File file_ = do path <- Data.List.NonEmpty.some1 pathComponent 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_ query <- optional (("?" :: Parser Text) *> query_) fragment <- optional (("#" :: Parser Text) *> fragment_) 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 (range 0 1 (h16 <> ":") <> h16) <> "::" <> count 3 (h16 <> ":") <> ls32 alternative4 = option (range 0 2 (h16 <> ":") <> h16) <> "::" <> count 2 (h16 <> ":") <> ls32 alternative5 = option (range 0 3 (h16 <> ":") <> h16) <> "::" <> h16 <> ":" <> ls32 alternative6 = option (range 0 4 (h16 <> ":") <> h16) <> "::" <> ls32 alternative7 = option (range 0 5 (h16 <> ":") <> h16) <> "::" <> h16 alternative8 = option (range 0 6 (h16 <> ":") <> h16) <> "::" h16 :: Parser 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 == '?' fragment_ :: Parser Text fragment_ = 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" _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 dhall-1.19.1/src/Dhall/Pretty/0000755000000000000000000000000013377175666014204 5ustar0000000000000000dhall-1.19.1/src/Dhall/Pretty/Internal.hs0000644000000000000000000007664213377175666016333 0ustar0000000000000000{-# 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 , 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 characterSet = enclose' "" " " (" " <> rarrow characterSet <> " ") (rarrow characterSet <> space) {-| Format an expression that holds a variable number of elements, such as a list, record, or union -} enclose :: Doc ann -- ^ Beginning document for compact representation -> Doc ann -- ^ Beginning document for multi-line representation -> Doc ann -- ^ Separator for compact representation -> Doc ann -- ^ Separator for multi-line representation -> Doc ann -- ^ Ending document for compact representation -> Doc ann -- ^ Ending document for multi-line representation -> [(Doc ann, Doc ann)] -- ^ Elements to format, each of which is a pair: @(compact, multi-line)@ -> Doc ann enclose beginShort _ _ _ endShort _ [] = beginShort <> endShort where enclose beginShort beginLong sepShort sepLong endShort endLong docs = Pretty.group (Pretty.flatAlt (Pretty.align (mconcat (zipWith combineLong (beginLong : repeat sepLong) docsLong) <> endLong) ) (mconcat (zipWith combineShort (beginShort : repeat sepShort) docsShort) <> endShort) ) where docsShort = fmap fst docs docsLong = fmap snd docs combineLong x y = x <> y <> Pretty.hardline combineShort x y = x <> y {-| Format an expression that holds a variable number of elements without a trailing document such as nested `let`, nested lambdas, or nested `forall`s -} enclose' :: Doc ann -- ^ Beginning document for compact representation -> Doc ann -- ^ Beginning document for multi-line representation -> Doc ann -- ^ Separator for compact representation -> Doc ann -- ^ Separator for multi-line representation -> [(Doc ann, Doc ann)] -- ^ Elements to format, each of which is a pair: @(compact, multi-line)@ -> Doc ann enclose' beginShort beginLong sepShort sepLong docs = Pretty.group (Pretty.flatAlt long short) where longLines = zipWith (<>) (beginLong : repeat sepLong) docsLong long = Pretty.align (mconcat (Data.List.intersperse Pretty.hardline longLines)) short = mconcat (zipWith (<>) (beginShort : repeat sepShort) docsShort) docsShort = fmap fst docs docsLong = fmap snd docs alpha :: Char -> Bool alpha c = ('\x41' <= c && c <= '\x5A') || ('\x61' <= c && c <= '\x7A') digit :: Char -> Bool digit c = '\x30' <= c && c <= '\x39' headCharacter :: Char -> Bool headCharacter c = alpha c || c == '_' tailCharacter :: Char -> Bool tailCharacter c = alpha c || digit c || c == '_' || c == '-' || c == '/' prettyLabel :: Text -> Doc Ann prettyLabel a = label doc where doc = case Text.uncons a of Just (h, t) | headCharacter h && Text.all tailCharacter t && not (Data.HashSet.member a reservedIdentifiers) -> Pretty.pretty a _ -> backtick <> Pretty.pretty a <> backtick prettyLabels :: Set Text -> Doc Ann prettyLabels a | Data.Set.null (Dhall.Set.toSet a) = lbrace <> rbrace | otherwise = braces (map (duplicate . prettyLabel) (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 "∧" (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 "⫽" (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 "⩓" (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 Constructors _ -> 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 (Constructors b) = [ prettyImportExpression b , keyword "constructors" ] 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 <> prettyLabel b prettySelectorExpression (Project a b) = prettySelectorExpression a <> dot <> prettyLabels b 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 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) = ( prettyLabel key <> " " <> separator <> " " <> prettyExpression val , prettyLabel 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)) prettyUnion :: Pretty a => Map Text (Expr s a) -> Doc Ann prettyUnion = angles . map (prettyKeyValue colon) . Dhall.Map.toList prettyUnionLit :: Pretty a => Text -> Expr s a -> Map Text (Expr s a) -> Doc Ann prettyUnionLit a b c = angles (front : map adapt (Dhall.Map.toList c)) where front = prettyKeyValue equals (a, b) adapt = prettyKeyValue colon 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 dhall-1.19.1/src/Dhall/Pretty/Internal.hs-boot0000644000000000000000000000050113377175666017251 0ustar0000000000000000module Dhall.Pretty.Internal where import Data.Text (Text) import Data.Text.Prettyprint.Doc (Pretty, Doc) import {-# SOURCE #-} Dhall.Core data Ann prettyVar :: Var -> Doc Ann prettyConst :: Const -> Doc Ann prettyExpr :: Pretty a => Expr s a -> Doc Ann pretty :: Pretty a => a -> Text escapeText :: Text -> Text dhall-1.19.1/tests/0000755000000000000000000000000013377175666012244 5ustar0000000000000000dhall-1.19.1/tests/Format.hs0000644000000000000000000000713013377175666014031 0ustar0000000000000000{-# LANGUAGE OverloadedStrings #-} module Format where import Data.Monoid (mempty, (<>)) import Data.Text (Text) import Dhall.Pretty (CharacterSet(..)) import Test.Tasty (TestTree) import qualified Control.Exception import qualified Data.Text import qualified Data.Text.IO import qualified Data.Text.Prettyprint.Doc import qualified Data.Text.Prettyprint.Doc.Render.Text import qualified Dhall.Parser import qualified Dhall.Pretty import qualified Test.Tasty import qualified Test.Tasty.HUnit formatTests :: TestTree formatTests = Test.Tasty.testGroup "format tests" [ should Unicode "prefer multi-line strings when newlines present" "multiline" , should Unicode "escape ${ for single-quoted strings" "escapeSingleQuotedOpenInterpolation" , should Unicode "preserve the original order of fields" "fieldOrder" , should Unicode "preserve the original order of projections" "projectionOrder" , should Unicode "escape numeric labels correctly" "escapeNumericLabel" , should Unicode "correctly handle scientific notation with a large exponent" "largeExponent" , should Unicode "round a double to the nearest representable value. Ties go to even least significant bit" "doubleRound" , should Unicode "correctly format the empty record literal" "emptyRecord" , should Unicode "indent then/else to the same column" "ifThenElse" , should Unicode "handle indenting long imports correctly without trailing space per line" "importLines" , should Unicode "handle indenting small imports correctly without trailing space inline" "importLines2" , should Unicode "not remove parentheses when accessing a field of a record" "importAccess" , should Unicode "handle formatting sha256 imports correctly" "sha256Printing" , should Unicode "handle formatting of Import suffix correctly" "importSuffix" , should ASCII "be able to format with ASCII characters" "ascii" , should Unicode "preserve Unicode characters" "unicode" ] should :: CharacterSet -> Text -> Text -> TestTree should characterSet name basename = Test.Tasty.HUnit.testCase (Data.Text.unpack name) $ do let inputFile = Data.Text.unpack ("./tests/format/" <> basename <> "A.dhall") let outputFile = Data.Text.unpack ("./tests/format/" <> basename <> "B.dhall") inputText <- Data.Text.IO.readFile inputFile expr <- case Dhall.Parser.exprFromText mempty inputText of Left err -> Control.Exception.throwIO err Right expr -> return expr let doc = Dhall.Pretty.prettyCharacterSet characterSet expr let docStream = Data.Text.Prettyprint.Doc.layoutSmart Dhall.Pretty.layoutOpts doc let actualText = Data.Text.Prettyprint.Doc.Render.Text.renderStrict docStream expectedText <- Data.Text.IO.readFile outputFile let message = "The formatted expression did not match the expected output" Test.Tasty.HUnit.assertEqual message expectedText actualText dhall-1.19.1/tests/Import.hs0000644000000000000000000000747413377175666014066 0ustar0000000000000000{-# LANGUAGE OverloadedStrings #-} module Import where import Data.Text (Text) import Test.Tasty (TestTree) import Dhall.Import (MissingImports(..)) import Control.Exception (catch, throwIO) import Data.Monoid ((<>)) import qualified Control.Monad.Trans.State.Strict as State import qualified Data.Text import qualified Data.Text.IO import qualified Dhall.Parser import qualified Dhall.Import import qualified Test.Tasty import qualified Test.Tasty.HUnit importTests :: TestTree importTests = Test.Tasty.testGroup "import tests" [ Test.Tasty.testGroup "import alternatives" [ shouldFail 3 "alternative of several unset env variables" "./tests/import/failure/alternativeEnv.dhall" , shouldFail 1 "alternative of env variable and missing" "./tests/import/failure/alternativeEnvMissing.dhall" , shouldFail 0 "just missing" "./tests/import/failure/missing.dhall" , shouldNotFail "alternative of env variable, missing, and a Natural" "./tests/import/success/alternativeEnvNaturalA.dhall" , shouldNotFail "alternative of env variable and a Natural" "./tests/import/success/alternativeEnvSimpleA.dhall" , shouldNotFail "alternative of a Natural and missing" "./tests/import/success/alternativeNaturalA.dhall" ] , Test.Tasty.testGroup "import relative to argument" [ shouldNotFailRelative "works" "./tests/import/data/foo/bar" "./tests/import/success/relative.dhall" , shouldNotFailRelative "a semantic integrity check if fields are reordered" "./tests/import/success/" "./tests/import/success/fieldOrderA.dhall" , shouldNotFailRelative "a semantic integrity check when importing an expression using `constructors`" "./tests/import/success/" "./tests/import/success/issue553B.dhall" ] ] shouldNotFail :: Text -> FilePath -> TestTree shouldNotFail name path = Test.Tasty.HUnit.testCase (Data.Text.unpack name) (do text <- Data.Text.IO.readFile path actualExpr <- case Dhall.Parser.exprFromText mempty text of Left err -> throwIO err Right expr -> return expr _ <- Dhall.Import.load actualExpr return ()) shouldNotFailRelative :: Text -> FilePath -> FilePath -> TestTree shouldNotFailRelative name dir path = Test.Tasty.HUnit.testCase (Data.Text.unpack name) (do text <- Data.Text.IO.readFile path expr <- case Dhall.Parser.exprFromText mempty text of Left err -> throwIO err Right expr -> return expr _ <- State.evalStateT (Dhall.Import.loadWith expr) (Dhall.Import.emptyStatus dir) return ()) shouldFail :: Int -> Text -> FilePath -> TestTree shouldFail failures name path = Test.Tasty.HUnit.testCase (Data.Text.unpack name) (do text <- Data.Text.IO.readFile path actualExpr <- case Dhall.Parser.exprFromText mempty text of Left err -> throwIO err Right expr -> return expr catch (do _ <- Dhall.Import.load actualExpr fail "Import should have failed, but it succeeds") (\(MissingImports es) -> case length es == failures of True -> pure () False -> fail ("Should have failed " <> show failures <> " times, but failed with: \n" <> show es)) ) dhall-1.19.1/tests/Lint.hs0000644000000000000000000000345213377175666013512 0ustar0000000000000000{-# LANGUAGE OverloadedStrings #-} module Lint where import Data.Monoid (mempty, (<>)) import Data.Text (Text) import Test.Tasty (TestTree) import qualified Control.Exception import qualified Data.Text import qualified Data.Text.IO import qualified Dhall.Core import qualified Dhall.Import import qualified Dhall.Lint import qualified Dhall.Parser import qualified Test.Tasty import qualified Test.Tasty.HUnit lintTests :: TestTree lintTests = Test.Tasty.testGroup "format tests" [ should "correctly handle multi-let expressions" "success/multilet" ] should :: Text -> Text -> TestTree should name basename = Test.Tasty.HUnit.testCase (Data.Text.unpack name) $ do let inputFile = Data.Text.unpack ("./tests/lint/" <> basename <> "A.dhall") let outputFile = Data.Text.unpack ("./tests/lint/" <> basename <> "B.dhall") inputText <- Data.Text.IO.readFile inputFile parsedInput <- case Dhall.Parser.exprFromText mempty inputText of Left exception -> Control.Exception.throwIO exception Right expression -> return expression let lintedInput = Dhall.Lint.lint parsedInput actualExpression <- Dhall.Import.load lintedInput outputText <- Data.Text.IO.readFile outputFile parsedOutput <- case Dhall.Parser.exprFromText mempty outputText of Left exception -> Control.Exception.throwIO exception Right expression -> return expression resolvedOutput <- Dhall.Import.load parsedOutput let expectedExpression = Dhall.Core.denote resolvedOutput let message = "The linted expression did not match the expected output" Test.Tasty.HUnit.assertEqual message expectedExpression actualExpression dhall-1.19.1/tests/Normalization.hs0000644000000000000000000003652313377175666015437 0ustar0000000000000000{-# LANGUAGE OverloadedLists #-} {-# LANGUAGE OverloadedStrings #-} module Normalization (normalizationTests) where import Data.Monoid ((<>)) import Data.Text (Text) import Dhall.Core (Expr) import Dhall.TypeCheck (X) import qualified Control.Exception import qualified Data.Text import qualified Dhall.Core import qualified Dhall.Import import qualified Dhall.Parser import qualified Dhall.TypeCheck import Dhall.Core import Dhall.Context import Test.Tasty import Test.Tasty.HUnit import Util normalizationTests :: TestTree normalizationTests = testGroup "normalization" [ tutorialExamples , preludeExamples , simplifications , constantFolding , conversions , shouldNormalize "Optional build/fold fusion" "success/simple/optionalBuildFold" , customization , shouldNormalize "a remote-systems.conf builder" "success/remoteSystems" , shouldNormalize "multi-line strings correctly" "success/simple/multiLine" , shouldNormalize "the // operator and sort the fields" "success/simple/sortOperator" ] tutorialExamples :: TestTree tutorialExamples = testGroup "Tutorial examples" [ shouldNormalize "⩓" "./success/haskell-tutorial/combineTypes/0" , shouldNormalize "//\\\\" "./success/haskell-tutorial/combineTypes/1" , shouldNormalize "//" "./success/haskell-tutorial/prefer/0" , shouldNormalize "projection" "./success/haskell-tutorial/projection/0" , shouldNormalize "access record" "./success/haskell-tutorial/access/0" , shouldNormalize "access union" "./success/haskell-tutorial/access/1" ] preludeExamples :: TestTree preludeExamples = testGroup "Prelude examples" [ shouldNormalize "Bool/and" "./success/prelude/Bool/and/0" , shouldNormalize "Bool/and" "./success/prelude/Bool/and/1" , shouldNormalize "Bool/build" "./success/prelude/Bool/build/0" , shouldNormalize "Bool/build" "./success/prelude/Bool/build/1" , shouldNormalize "Bool/even" "./success/prelude/Bool/even/0" , shouldNormalize "Bool/even" "./success/prelude/Bool/even/1" , shouldNormalize "Bool/even" "./success/prelude/Bool/even/2" , shouldNormalize "Bool/even" "./success/prelude/Bool/even/3" , shouldNormalize "Bool/fold" "./success/prelude/Bool/fold/0" , shouldNormalize "Bool/fold" "./success/prelude/Bool/fold/1" , shouldNormalize "Bool/not" "./success/prelude/Bool/not/0" , shouldNormalize "Bool/not" "./success/prelude/Bool/not/1" , shouldNormalize "Bool/odd" "./success/prelude/Bool/odd/0" , shouldNormalize "Bool/odd" "./success/prelude/Bool/odd/1" , shouldNormalize "Bool/odd" "./success/prelude/Bool/odd/2" , shouldNormalize "Bool/odd" "./success/prelude/Bool/odd/3" , shouldNormalize "Bool/or" "./success/prelude/Bool/or/0" , shouldNormalize "Bool/or" "./success/prelude/Bool/or/1" , shouldNormalize "Bool/show" "./success/prelude/Bool/show/0" , shouldNormalize "Bool/show" "./success/prelude/Bool/show/1" , shouldNormalize "Double/show" "./success/prelude/Double/show/0" , shouldNormalize "Double/show" "./success/prelude/Double/show/1" , shouldNormalize "Integer/show" "./success/prelude/Integer/show/0" , shouldNormalize "Integer/show" "./success/prelude/Integer/show/1" , shouldNormalize "Integer/toDouble" "./success/prelude/Integer/toDouble/0" , shouldNormalize "Integer/toDouble" "./success/prelude/Integer/toDouble/1" , shouldNormalize "List/all" "./success/prelude/List/all/0" , shouldNormalize "List/all" "./success/prelude/List/all/1" , shouldNormalize "List/any" "./success/prelude/List/any/0" , shouldNormalize "List/any" "./success/prelude/List/any/1" , shouldNormalize "List/build" "./success/prelude/List/build/0" , shouldNormalize "List/build" "./success/prelude/List/build/1" , shouldNormalize "List/concat" "./success/prelude/List/concat/0" , shouldNormalize "List/concat" "./success/prelude/List/concat/1" , shouldNormalize "List/concatMap" "./success/prelude/List/concatMap/0" , shouldNormalize "List/concatMap" "./success/prelude/List/concatMap/1" , shouldNormalize "List/filter" "./success/prelude/List/filter/0" , shouldNormalize "List/filter" "./success/prelude/List/filter/1" , shouldNormalize "List/fold" "./success/prelude/List/fold/0" , shouldNormalize "List/fold" "./success/prelude/List/fold/1" , shouldNormalize "List/fold" "./success/prelude/List/fold/2" , shouldNormalize "List/generate" "./success/prelude/List/generate/0" , shouldNormalize "List/generate" "./success/prelude/List/generate/1" , shouldNormalize "List/head" "./success/prelude/List/head/0" , shouldNormalize "List/head" "./success/prelude/List/head/1" , shouldNormalize "List/indexed" "./success/prelude/List/indexed/0" , shouldNormalize "List/indexed" "./success/prelude/List/indexed/1" , shouldNormalize "List/iterate" "./success/prelude/List/iterate/0" , shouldNormalize "List/iterate" "./success/prelude/List/iterate/1" , shouldNormalize "List/last" "./success/prelude/List/last/0" , shouldNormalize "List/last" "./success/prelude/List/last/1" , shouldNormalize "List/length" "./success/prelude/List/length/0" , shouldNormalize "List/length" "./success/prelude/List/length/1" , shouldNormalize "List/map" "./success/prelude/List/map/0" , shouldNormalize "List/map" "./success/prelude/List/map/1" , shouldNormalize "List/null" "./success/prelude/List/null/0" , shouldNormalize "List/null" "./success/prelude/List/null/1" , shouldNormalize "List/replicate" "./success/prelude/List/replicate/0" , shouldNormalize "List/replicate" "./success/prelude/List/replicate/1" , shouldNormalize "List/reverse" "./success/prelude/List/reverse/0" , shouldNormalize "List/reverse" "./success/prelude/List/reverse/1" , shouldNormalize "List/shifted" "./success/prelude/List/shifted/0" , shouldNormalize "List/shifted" "./success/prelude/List/shifted/1" , shouldNormalize "List/unzip" "./success/prelude/List/unzip/0" , shouldNormalize "List/unzip" "./success/prelude/List/unzip/1" , shouldNormalize "Natural/build" "./success/prelude/Natural/build/0" , shouldNormalize "Natural/build" "./success/prelude/Natural/build/1" , shouldNormalize "Natural/enumerate" "./success/prelude/Natural/enumerate/0" , shouldNormalize "Natural/enumerate" "./success/prelude/Natural/enumerate/1" , shouldNormalize "Natural/even" "./success/prelude/Natural/even/0" , shouldNormalize "Natural/even" "./success/prelude/Natural/even/1" , shouldNormalize "Natural/fold" "./success/prelude/Natural/fold/0" , shouldNormalize "Natural/fold" "./success/prelude/Natural/fold/1" , shouldNormalize "Natural/fold" "./success/prelude/Natural/fold/2" , shouldNormalize "Natural/isZero" "./success/prelude/Natural/isZero/0" , shouldNormalize "Natural/isZero" "./success/prelude/Natural/isZero/1" , shouldNormalize "Natural/odd" "./success/prelude/Natural/odd/0" , shouldNormalize "Natural/odd" "./success/prelude/Natural/odd/1" , shouldNormalize "Natural/product" "./success/prelude/Natural/product/0" , shouldNormalize "Natural/product" "./success/prelude/Natural/product/1" , shouldNormalize "Natural/show" "./success/prelude/Natural/show/0" , shouldNormalize "Natural/show" "./success/prelude/Natural/show/1" , shouldNormalize "Natural/sum" "./success/prelude/Natural/sum/0" , shouldNormalize "Natural/sum" "./success/prelude/Natural/sum/1" , shouldNormalize "Natural/toDouble" "./success/prelude/Natural/toDouble/0" , shouldNormalize "Natural/toDouble" "./success/prelude/Natural/toDouble/1" , shouldNormalize "Natural/toInteger" "./success/prelude/Natural/toInteger/0" , shouldNormalize "Natural/toInteger" "./success/prelude/Natural/toInteger/1" , shouldNormalize "Optional/all" "./success/prelude/Optional/all/0" , shouldNormalize "Optional/all" "./success/prelude/Optional/all/1" , shouldNormalize "Optional/any" "./success/prelude/Optional/any/0" , shouldNormalize "Optional/any" "./success/prelude/Optional/any/1" , shouldNormalize "Optional/build" "./success/prelude/Optional/build/0" , shouldNormalize "Optional/build" "./success/prelude/Optional/build/1" , shouldNormalize "Optional/concat" "./success/prelude/Optional/concat/0" , shouldNormalize "Optional/concat" "./success/prelude/Optional/concat/1" , shouldNormalize "Optional/concat" "./success/prelude/Optional/concat/2" , shouldNormalize "Optional/filter" "./success/prelude/Optional/filter/0" , shouldNormalize "Optional/filter" "./success/prelude/Optional/filter/1" , shouldNormalize "Optional/fold" "./success/prelude/Optional/fold/0" , shouldNormalize "Optional/fold" "./success/prelude/Optional/fold/1" , shouldNormalize "Optional/head" "./success/prelude/Optional/head/0" , shouldNormalize "Optional/head" "./success/prelude/Optional/head/1" , shouldNormalize "Optional/head" "./success/prelude/Optional/head/2" , shouldNormalize "Optional/last" "./success/prelude/Optional/last/0" , shouldNormalize "Optional/last" "./success/prelude/Optional/last/1" , shouldNormalize "Optional/last" "./success/prelude/Optional/last/2" , shouldNormalize "Optional/length" "./success/prelude/Optional/length/0" , shouldNormalize "Optional/length" "./success/prelude/Optional/length/1" , shouldNormalize "Optional/map" "./success/prelude/Optional/map/0" , shouldNormalize "Optional/map" "./success/prelude/Optional/map/1" , shouldNormalize "Optional/null" "./success/prelude/Optional/null/0" , shouldNormalize "Optional/null" "./success/prelude/Optional/null/1" , shouldNormalize "Optional/toList" "./success/prelude/Optional/toList/0" , shouldNormalize "Optional/toList" "./success/prelude/Optional/toList/1" , shouldNormalize "Optional/unzip" "./success/prelude/Optional/unzip/0" , shouldNormalize "Optional/unzip" "./success/prelude/Optional/unzip/1" , shouldNormalize "Text/concat" "./success/prelude/Text/concat/0" , shouldNormalize "Text/concat" "./success/prelude/Text/concat/1" , shouldNormalize "Text/concatMap" "./success/prelude/Text/concatMap/0" , shouldNormalize "Text/concatMap" "./success/prelude/Text/concatMap/1" , shouldNormalize "Text/concatMapSep" "./success/prelude/Text/concatMapSep/0" , shouldNormalize "Text/concatMapSep" "./success/prelude/Text/concatMapSep/1" , shouldNormalize "Text/concatSep" "./success/prelude/Text/concatSep/0" , shouldNormalize "Text/concatSep" "./success/prelude/Text/concatSep/1" ] simplifications :: TestTree simplifications = testGroup "Simplifications" [ shouldNormalize "if/then/else" "./success/simplifications/ifThenElse" , shouldNormalize "||" "./success/simplifications/or" , shouldNormalize "&&" "./success/simplifications/and" , shouldNormalize "==" "./success/simplifications/eq" , shouldNormalize "!=" "./success/simplifications/ne" ] constantFolding :: TestTree constantFolding = testGroup "folding of constants" [ shouldNormalize "Natural/plus" "success/simple/naturalPlus" , shouldNormalize "Optional/fold" "success/simple/optionalFold" , shouldNormalize "Optional/build" "success/simple/optionalBuild" , shouldNormalize "Natural/build" "success/simple/naturalBuild" ] conversions :: TestTree conversions = testGroup "conversions" [ shouldNormalize "Natural/show" "success/simple/naturalShow" , shouldNormalize "Integer/show" "success/simple/integerShow" , shouldNormalize "Double/show" "success/simple/doubleShow" , shouldNormalize "Natural/toInteger" "success/simple/naturalToInteger" , shouldNormalize "Integer/toDouble" "success/simple/integerToDouble" ] customization :: TestTree customization = testGroup "customization" [ simpleCustomization , nestedReduction ] simpleCustomization :: TestTree simpleCustomization = testCase "simpleCustomization" $ do let tyCtx = insert "min" (Pi "_" Natural (Pi "_" Natural Natural)) empty valCtx e = case e of (App (App (Var (V "min" 0)) (NaturalLit x)) (NaturalLit y)) -> pure (Just (NaturalLit (min x y))) _ -> pure Nothing e <- codeWith tyCtx "min (min 11 12) 8 + 1" assertNormalizesToWith valCtx e "9" nestedReduction :: TestTree nestedReduction = testCase "doubleReduction" $ do minType <- insert "min" <$> code "Natural → Natural → Natural" fiveorlessType <- insert "fiveorless" <$> code "Natural → Natural" wurbleType <- insert "wurble" <$> code "Natural → Integer" let tyCtx = minType . fiveorlessType . wurbleType $ empty valCtx e = case e of (App (App (Var (V "min" 0)) (NaturalLit x)) (NaturalLit y)) -> pure (Just (NaturalLit (min x y))) (App (Var (V "wurble" 0)) (NaturalLit x)) -> pure (Just (App (Var (V "fiveorless" 0)) (NaturalPlus (NaturalLit x) (NaturalLit 2)))) (App (Var (V "fiveorless" 0)) (NaturalLit x)) -> pure (Just (App (App (Var (V "min" 0)) (NaturalLit x)) (NaturalPlus (NaturalLit 3) (NaturalLit 2)))) _ -> pure Nothing e <- codeWith tyCtx "wurble 6" assertNormalizesToWith valCtx e "5" should :: Text -> Text -> TestTree should name basename = Test.Tasty.HUnit.testCase (Data.Text.unpack name) $ do let actualCode = "./tests/normalization/" <> basename <> "A.dhall" let expectedCode = "./tests/normalization/" <> basename <> "B.dhall" actualExpr <- case Dhall.Parser.exprFromText mempty actualCode of Left err -> Control.Exception.throwIO err Right expr -> return expr actualResolved <- Dhall.Import.load actualExpr case Dhall.TypeCheck.typeOf actualResolved of Left err -> Control.Exception.throwIO err Right _ -> return () let actualNormalized = Dhall.Core.alphaNormalize (Dhall.Core.normalize actualResolved :: Expr X X) expectedExpr <- case Dhall.Parser.exprFromText mempty expectedCode of Left err -> Control.Exception.throwIO err Right expr -> return expr expectedResolved <- Dhall.Import.load expectedExpr case Dhall.TypeCheck.typeOf expectedResolved of Left err -> Control.Exception.throwIO err Right _ -> return () -- Use `denote` instead of `normalize` to enforce that the expected -- expression is already in normal form let expectedNormalized = Dhall.Core.alphaNormalize (Dhall.Core.denote expectedResolved) let message = "The normalized expression did not match the expected output" Test.Tasty.HUnit.assertEqual message expectedNormalized actualNormalized shouldNormalize :: Text -> Text -> TestTree shouldNormalize name = should ("normalize " <> name <> " correctly") dhall-1.19.1/tests/Parser.hs0000644000000000000000000001367313377175666014046 0ustar0000000000000000{-# LANGUAGE OverloadedStrings #-} module Parser where import Data.Text (Text) import Test.Tasty (TestTree) import qualified Control.Exception import qualified Data.Text import qualified Data.Text.IO import qualified Dhall.Parser import qualified Test.Tasty import qualified Test.Tasty.HUnit parserTests :: TestTree parserTests = Test.Tasty.testGroup "parser tests" [ Test.Tasty.testGroup "whitespace" [ shouldParse "prefix/suffix" "./tests/parser/success/whitespace" , shouldParse "block comment" "./tests/parser/success/blockComment" , shouldParse "nested block comment" "./tests/parser/success/nestedBlockComment" , shouldParse "line comment" "./tests/parser/success/lineComment" , shouldParse "Unicode comment" "./tests/parser/success/unicodeComment" , shouldParse "whitespace buffet" "./tests/parser/success/whitespaceBuffet" ] , shouldParse "label" "./tests/parser/success/label" , shouldParse "quoted label" "./tests/parser/success/quotedLabel" , shouldParse "double quoted string" "./tests/parser/success/doubleQuotedString" , shouldParse "Unicode double quoted string" "./tests/parser/success/unicodeDoubleQuotedString" , shouldParse "escaped double quoted string" "./tests/parser/success/escapedDoubleQuotedString" , shouldParse "interpolated double quoted string" "./tests/parser/success/interpolatedDoubleQuotedString" , shouldParse "single quoted string" "./tests/parser/success/singleQuotedString" , shouldParse "escaped single quoted string" "./tests/parser/success/escapedSingleQuotedString" , shouldParse "interpolated single quoted string" "./tests/parser/success/interpolatedSingleQuotedString" , shouldParse "double" "./tests/parser/success/double" , shouldParse "natural" "./tests/parser/success/natural" , shouldParse "identifier" "./tests/parser/success/identifier" , shouldParse "paths" "./tests/parser/success/paths" , shouldParse "path termination" "./tests/parser/success/pathTermination" , shouldParse "urls" "./tests/parser/success/urls" , shouldParse "environmentVariables" "./tests/parser/success/environmentVariables" , shouldParse "lambda" "./tests/parser/success/lambda" , shouldParse "if then else" "./tests/parser/success/ifThenElse" , shouldParse "let" "./tests/parser/success/let" , shouldParse "forall" "./tests/parser/success/forall" , shouldParse "function type" "./tests/parser/success/functionType" , shouldParse "operators" "./tests/parser/success/operators" , shouldParse "annotations" "./tests/parser/success/annotations" , shouldParse "merge" "./tests/parser/success/merge" , shouldParse "constructors" "./tests/parser/success/constructors" , shouldParse "fields" "./tests/parser/success/fields" , shouldParse "record" "./tests/parser/success/record" , shouldParse "union" "./tests/parser/success/union" , shouldParse "list" "./tests/parser/success/list" , shouldParse "builtins" "./tests/parser/success/builtins" , shouldParse "import alternatives" "./tests/parser/success/importAlt" , shouldParse "large expression" "./tests/parser/success/largeExpression" , shouldParse "names that begin with reserved identifiers" "./tests/parser/success/reservedPrefix" , shouldParse "interpolated expressions with leading whitespace" "./tests/parser/success/template" , shouldParse "collections with type annotations containing imports" "./tests/parser/success/collectionImportType" , shouldParse "a parenthesized custom header import" "./tests/parser/success/parenthesizeUsing" , shouldNotParse "accessing a field of an import without parentheses" "./tests/parser/failure/importAccess.dhall" , shouldParse "Sort" "./tests/parser/success/sort" , shouldParse "quoted path components" "./tests/parser/success/quotedPaths" , shouldNotParse "positive double out of bounds" "./tests/parser/failure/doubleBoundsPos.dhall" , shouldNotParse "negative double out of bounds" "./tests/parser/failure/doubleBoundsNeg.dhall" ] shouldParse :: Text -> FilePath -> TestTree shouldParse name path = Test.Tasty.HUnit.testCase (Data.Text.unpack name) (do text <- Data.Text.IO.readFile (path <> "A.dhall") case Dhall.Parser.exprFromText mempty text of Left err -> Control.Exception.throwIO err Right _ -> return () ) shouldNotParse :: Text -> FilePath -> TestTree shouldNotParse name path = Test.Tasty.HUnit.testCase (Data.Text.unpack name) (do text <- Data.Text.IO.readFile path case Dhall.Parser.exprFromText mempty text of Left _ -> return () Right _ -> fail "Unexpected successful parser" ) dhall-1.19.1/tests/QuickCheck.hs0000644000000000000000000002602113377175666014613 0ustar0000000000000000{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE StandaloneDeriving #-} {-# OPTIONS_GHC -fno-warn-orphans #-} module QuickCheck where import Codec.Serialise (DeserialiseFailure(..)) import Control.Monad (guard) import Data.List.NonEmpty (NonEmpty(..)) import Dhall.Map (Map) import Dhall.Core ( Binding(..) , Chunks(..) , Const(..) , Directory(..) , Expr(..) , File(..) , FilePrefix(..) , Import(..) , ImportHashed(..) , ImportMode(..) , ImportType(..) , Scheme(..) , URL(..) , Var(..) ) import Dhall.Set (Set) import Numeric.Natural (Natural) import Test.QuickCheck (Arbitrary(..), Gen, Property, genericShrink, (===)) import Test.QuickCheck.Instances () import Test.Tasty (TestTree) import qualified Codec.Serialise import qualified Data.Coerce import qualified Dhall.Map import qualified Data.Sequence import qualified Dhall.Binary import qualified Dhall.Core import qualified Dhall.Set import qualified Test.QuickCheck import qualified Test.Tasty.QuickCheck 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 lift0 :: a -> Gen a lift0 = pure lift1 :: Arbitrary a => (a -> b) -> Gen b lift1 f = f <$> arbitrary lift2 :: (Arbitrary a, Arbitrary b) => (a -> b -> c) -> Gen c lift2 f = f <$> arbitrary <*> arbitrary lift3 :: (Arbitrary a, Arbitrary b, Arbitrary c) => (a -> b -> c -> d) -> Gen d lift3 f = f <$> arbitrary <*> arbitrary <*> arbitrary lift4 :: (Arbitrary a, Arbitrary b, Arbitrary c, Arbitrary d) => (a -> b -> c -> d -> e) -> Gen e lift4 f = f <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary lift5 :: ( Arbitrary a , Arbitrary b , Arbitrary c , Arbitrary d , Arbitrary e ) => (a -> b -> c -> d -> e -> f) -> Gen f lift5 f = f <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary lift6 :: ( Arbitrary a , Arbitrary b , Arbitrary c , Arbitrary d , Arbitrary e , Arbitrary f ) => (a -> b -> c -> d -> e -> f -> g) -> Gen g lift6 f = f <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary 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 [ (7, arbitrary) , (1, fmap (\x -> x + (2 ^ (64 :: Int))) arbitrary) , (1, fmap (\x -> x - (2 ^ (64 :: Int))) arbitrary) ] instance (Ord k, Arbitrary k, Arbitrary v) => Arbitrary (Map k v) where arbitrary = do n <- Test.QuickCheck.choose (0, 2) kvs <- Test.QuickCheck.vectorOf n ((,) <$> arbitrary <*> arbitrary) return (Dhall.Map.fromList kvs) shrink = map Dhall.Map.fromList . shrink . Dhall.Map.toList instance (Arbitrary s, Arbitrary a) => Arbitrary (Binding s a) where arbitrary = lift3 Binding shrink = genericShrink instance (Arbitrary s, Arbitrary a) => Arbitrary (Chunks s a) where arbitrary = do n <- Test.QuickCheck.choose (0, 2) Chunks <$> Test.QuickCheck.vectorOf n arbitrary <*> arbitrary shrink = genericShrink instance Arbitrary Const where arbitrary = Test.QuickCheck.oneof [ pure Type, pure Kind, pure Sort ] shrink = genericShrink instance Arbitrary Directory where arbitrary = lift1 Directory shrink = genericShrink averageDepth :: Natural averageDepth = 3 averageNumberOfSubExpressions :: Double averageNumberOfSubExpressions = 1 - 1 / fromIntegral averageDepth probabilityOfNullaryConstructor :: Double probabilityOfNullaryConstructor = 1 / fromIntegral averageDepth numberOfConstructors :: Natural numberOfConstructors = 50 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 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, lift1 Constructors) , ( 1, lift2 Field) , ( 1, lift2 Project) , ( 7, lift1 Embed) ] ) standardizedExpression 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 instance Arbitrary File where arbitrary = lift2 File shrink = genericShrink instance Arbitrary FilePrefix where arbitrary = Test.QuickCheck.oneof [ pure Absolute, pure Here, pure Home ] shrink = genericShrink instance Arbitrary ImportType where arbitrary = Test.QuickCheck.suchThat (Test.QuickCheck.oneof [ lift2 Local , lift5 (\a b c d e -> Remote (URL a b c d e Nothing)) , lift1 Env , lift0 Missing ] ) standardizedImportType shrink importType = filter standardizedImportType (genericShrink importType) standardizedImportType :: ImportType -> Bool standardizedImportType (Remote (URL _ _ _ _ _ (Just _))) = False standardizedImportType _ = True instance Arbitrary ImportHashed where arbitrary = Test.QuickCheck.suchThat (lift1 (ImportHashed Nothing)) standardizedImportHashed shrink (ImportHashed { importType = oldImportType, .. }) = do newImportType <- shrink oldImportType let importHashed = ImportHashed { importType = newImportType, .. } guard (standardizedImportHashed importHashed) return importHashed standardizedImportHashed :: ImportHashed -> Bool standardizedImportHashed (ImportHashed (Just _) _) = False standardizedImportHashed _ = True -- The standard does not yet specify how to encode `as Text`, so don't test it -- yet instance Arbitrary ImportMode where arbitrary = lift0 Code shrink = genericShrink instance Arbitrary Import where arbitrary = lift2 Import shrink = genericShrink instance Arbitrary Scheme where arbitrary = Test.QuickCheck.oneof [ pure HTTP, pure HTTPS ] shrink = genericShrink instance Arbitrary URL where arbitrary = lift6 URL shrink = genericShrink instance Arbitrary Var where arbitrary = Test.QuickCheck.oneof [ fmap (V "_") natural , lift1 (\t -> V t 0) , lift1 V <*> natural ] shrink = genericShrink binaryRoundtrip :: Expr () Import -> Property binaryRoundtrip expression = wrap (fmap Dhall.Binary.decodeWithVersion (Codec.Serialise.deserialiseOrFail (Codec.Serialise.serialise (Dhall.Binary.encodeWithVersion Dhall.Binary.defaultStandardVersion expression) ) ) ) === wrap (Right (Right expression)) where wrap :: Either DeserialiseFailure a -> Either DeserialiseFailureWithEq a wrap = Data.Coerce.coerce isNormalizedIsConsistentWithNormalize :: Expr () Import -> Property isNormalizedIsConsistentWithNormalize expression = Dhall.Core.isNormalized expression === (Dhall.Core.normalize expression == expression) quickcheckTests :: TestTree quickcheckTests = Test.Tasty.QuickCheck.testProperties "QuickCheck" [ ( "Binary serialization should round-trip" , Test.QuickCheck.property binaryRoundtrip ) , ( "isNormalized should be consistent with normalize" , Test.QuickCheck.property (Test.QuickCheck.withMaxSuccess 10000 isNormalizedIsConsistentWithNormalize) ) ] dhall-1.19.1/tests/Regression.hs0000644000000000000000000002401613377175666014723 0ustar0000000000000000{-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE OverloadedStrings #-} module Regression where import qualified Control.Exception import qualified Data.Text.Lazy.IO import qualified Data.Text.Prettyprint.Doc import qualified Data.Text.Prettyprint.Doc.Render.Text import qualified Dhall import qualified Dhall.Context import qualified Dhall.Core import qualified Dhall.Map import qualified Dhall.Parser import qualified Dhall.Pretty import qualified Dhall.TypeCheck import qualified System.Timeout import qualified Test.Tasty import qualified Test.Tasty.HUnit import qualified Util import Control.DeepSeq (($!!)) import Dhall.Import (Imported) import Dhall.Parser (Src) import Dhall.TypeCheck (TypeError, X) import Test.Tasty (TestTree) import Test.Tasty.HUnit ((@?=)) regressionTests :: TestTree regressionTests = Test.Tasty.testGroup "regression tests" [ issue96 , issue126 , issue151 , issue164 , issue201 , issue209 , issue216 , issue253 , parsing0 , typeChecking0 , typeChecking1 , typeChecking2 , unnamedFields , trailingSpaceAfterStringLiterals ] data Foo = Foo Integer Bool | Bar Bool Bool Bool | Baz Integer Integer deriving (Show, Dhall.Generic, Dhall.Interpret, Dhall.Inject) unnamedFields :: TestTree unnamedFields = Test.Tasty.HUnit.testCase "Unnamed Fields" (do let ty = Dhall.auto :: Dhall.Type Foo Test.Tasty.HUnit.assertEqual "Good type" (Dhall.expected ty) (Dhall.Core.Union (Dhall.Map.fromList [ ("Foo",Dhall.Core.Record (Dhall.Map.fromList [ ("_1",Dhall.Core.Integer),("_2",Dhall.Core.Bool)])) , ("Bar",Dhall.Core.Record (Dhall.Map.fromList [ ("_1",Dhall.Core.Bool),("_2",Dhall.Core.Bool),("_3",Dhall.Core.Bool)])) , ("Baz",Dhall.Core.Record (Dhall.Map.fromList [ ("_1",Dhall.Core.Integer),("_2",Dhall.Core.Integer)])) ] ) ) let inj = Dhall.inject :: Dhall.InputType Foo Test.Tasty.HUnit.assertEqual "Good Inject" (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_in = Dhall.inject :: Dhall.InputType (Integer, Bool) Test.Tasty.HUnit.assertEqual "Inj. Tuple" (Dhall.declared tu_in) (Dhall.expected tu_ty) return () ) issue96 :: TestTree issue96 = Test.Tasty.HUnit.testCase "Issue #96" (do -- Verify that parsing should not fail _ <- Util.code "\"bar'baz\"" return () ) issue126 :: TestTree issue126 = Test.Tasty.HUnit.testCase "Issue #126" (do e <- Util.code "''\n\ \ foo\n\ \ bar\n\ \''" Util.normalize' e @?= "''\nfoo\nbar\n''" ) issue151 :: TestTree issue151 = Test.Tasty.HUnit.testCase "Issue #151" (do let shouldNotTypeCheck text = do let handler :: Imported (TypeError Src X) -> IO Bool handler _ = return True let typeCheck = do _ <- Util.code text return False b <- Control.Exception.handle handler typeCheck Test.Tasty.HUnit.assertBool "The expression should not type-check" b -- These two examples contain the following expression that loops infinitely -- if you normalize the expression before type-checking the expression: -- -- (λ(x : A) → x x) (λ(x : A) → x x) -- -- There was a bug in the Dhall type-checker were expressions were not -- being type-checked before being added to the context (which is a -- violation of the standard type-checking rules for a pure type system). -- The reason this is problematic is that several places in the -- type-checking logic assume that the context is safe to normalize. -- -- Both of these examples exercise area of the type-checker logic that -- assume that the context is normalized. If you fail to type-check terms -- before adding them to the context then this test will "fail" with an -- infinite loop. This test "succeeds" if the examples terminate -- immediately with a type-checking failure. shouldNotTypeCheck "./tests/regression/issue151a.dhall" shouldNotTypeCheck "./tests/regression/issue151b.dhall" ) issue164 :: TestTree issue164 = Test.Tasty.HUnit.testCase "Issue #164" (do -- Verify that parsing should not fail on a single-quote within a -- single-quoted string _ <- Util.code "./tests/regression/issue164.dhall" return () ) issue201 :: TestTree issue201 = Test.Tasty.HUnit.testCase "Issue #201" (do -- Verify that type synonyms work _ <- Util.code "./tests/regression/issue201.dhall" return () ) issue209 :: TestTree issue209 = Test.Tasty.HUnit.testCase "Issue #209" (do -- Verify that pretty-printing `constructors` doesn't trigger an infinite -- loop e <- Util.code "./tests/regression/issue209.dhall" let text = Dhall.Core.pretty e Just _ <- System.Timeout.timeout 1000000 (Control.Exception.evaluate $!! text) return () ) 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 text1 <- Data.Text.Lazy.IO.readFile "./tests/regression/issue216b.dhall" Test.Tasty.HUnit.assertEqual "Pretty-printing should preserve string interpolation" text1 text0 ) issue253 :: TestTree issue253 = Test.Tasty.HUnit.testCase "Issue #253" (do -- Verify that type-checking rejects ill-formed custom contexts let context = Dhall.Context.insert "x" "x" Dhall.Context.empty let result = Dhall.TypeCheck.typeWith context "x" -- If the context is not validated correctly then type-checking will -- infinitely loop Just _ <- System.Timeout.timeout 1000000 (Control.Exception.evaluate $! result) return () ) parsing0 :: TestTree parsing0 = Test.Tasty.HUnit.testCase "Parsing regression #0" (do -- Verify that parsing should not fail -- -- In 267093f8cddf1c2f909f2d997c31fd0a7cb2440a I broke the parser when left -- factoring the grammer by failing to handle the source tested by this -- regression test. The root of the problem was that the parser was trying -- to parse `List ./Node` as `Field List "/Node"` instead of -- `App List (Embed (Path (File Homeless "./Node") Code))`. The latter is -- the correct parse because `/Node` is not a valid field label, but the -- mistaken parser was committed to the incorrect parse and never attempted -- the correct parse. case Dhall.Parser.exprFromText mempty "List ./Node" of Left e -> Control.Exception.throwIO e Right _ -> return () ) typeChecking0 :: TestTree typeChecking0 = Test.Tasty.HUnit.testCase "Type-checking regression #0" (do -- There used to be a bug in the type-checking logic where `T` would be -- added to the context when inferring the type of `λ(x : T) → x`, but was -- missing from the context when inferring the kind of the inferred type -- (i.e. the kind of `∀(x : T) → T`). This led to an unbound variable -- error when inferring the kind -- -- This bug was originally reported in issue #10 _ <- Util.code "let Day : Type = Natural in λ(x : Day) → x" return () ) typeChecking1 :: TestTree typeChecking1 = Test.Tasty.HUnit.testCase "Type-checking regression #1" (do -- There used to be a bug in the type-checking logic when inferring the -- type of `let`. Specifically, given an expression of the form: -- -- let x : t = e1 in e2 -- -- ... the type-checker would not substitute `x` for `e1` in the inferred -- of the `let` expression. This meant that if the inferred type contained -- any references to `x` then these references would escape their scope and -- result in unbound variable exceptions -- -- This regression test exercises that code path by creating a `let` -- expression where the inferred type before substitution (`∀(x : b) → b` in -- this example), contains a reference to the `let`-bound variable (`b`) -- that needs to be substituted with `a` in order to produce the final -- correct inferred type (`∀(x : a) → a`). If this test passes then -- substitution worked correctly. If substitution doesn't occur then you -- expect an `Unbound variable` error from `b` escaping its scope due to -- being returned as part of the inferred type _ <- Util.code "λ(a : Type) → let b : Type = a in λ(x : b) → x" return () ) typeChecking2 :: TestTree typeChecking2 = Test.Tasty.HUnit.testCase "Type-checking regression #2" (do -- There used to be a bug in the type-checking logic where `let` bound -- variables would not correctly shadow variables of the same name when -- inferring the type of of the `let` expression -- -- This example exercises this code path with a `let` expression where the -- `let`-bound variable (`a`) has the same name as its own type (`a`). If -- shadowing works correctly then the final `a` in the expression should -- refer to the `let`-bound variable and not its type. An invalid reference -- to the shadowed type `a` would result in an invalid dependently typed -- function _ <- Util.code "λ(a : Type) → λ(x : a) → let a : a = x in a" return () ) trailingSpaceAfterStringLiterals :: TestTree trailingSpaceAfterStringLiterals = Test.Tasty.HUnit.testCase "Trailing space after string literals" (do -- Verify that string literals parse correctly with trailing space -- (Yes, I did get this wrong at some point) _ <- Util.code "(''ABC'' ++ \"DEF\" )" return () ) dhall-1.19.1/tests/Tests.hs0000644000000000000000000000155613377175666013711 0ustar0000000000000000module Main where import Lint (lintTests) import Normalization (normalizationTests) import Parser (parserTests) import Regression (regressionTests) import QuickCheck (quickcheckTests) import Tutorial (tutorialTests) import TypeCheck (typecheckTests) import Format (formatTests) import Import (importTests) import System.FilePath (()) import Test.Tasty import qualified System.Directory import qualified System.Environment allTests :: TestTree allTests = testGroup "Dhall Tests" [ normalizationTests , parserTests , regressionTests , tutorialTests , formatTests , typecheckTests , importTests , quickcheckTests , lintTests ] main :: IO () main = do pwd <- System.Directory.getCurrentDirectory System.Environment.setEnv "XDG_CACHE_HOME" (pwd ".cache") defaultMain allTests dhall-1.19.1/tests/Tutorial.hs0000644000000000000000000000607413377175666014412 0ustar0000000000000000{-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE OverloadedStrings #-} module Tutorial where import qualified Data.Vector import qualified Dhall import qualified Test.Tasty import qualified Test.Tasty.HUnit import qualified Util import Data.Monoid ((<>)) import Data.Text (Text) import Dhall (Inject) import GHC.Generics (Generic) import Numeric.Natural (Natural) import Test.Tasty (TestTree) import Test.Tasty.HUnit ((@?=)) tutorialTests :: TestTree tutorialTests = Test.Tasty.testGroup "tutorial" [ Test.Tasty.testGroup "Interpolation" [ _Interpolation_0 , _Interpolation_1 ] , Test.Tasty.testGroup "Functions" [ _Functions_0 , _Functions_1 , _Functions_2 ] , Test.Tasty.testGroup "Unions" [ example 0 "./tests/tutorial/unions0A.dhall" "./tests/tutorial/unions0B.dhall" , example 1 "./tests/tutorial/unions1A.dhall" "./tests/tutorial/unions1B.dhall" , example 2 "./tests/tutorial/unions2A.dhall" "./tests/tutorial/unions2B.dhall" , example 3 "./tests/tutorial/unions3A.dhall" "./tests/tutorial/unions3B.dhall" , example 4 "./tests/tutorial/unions4A.dhall" "./tests/tutorial/unions4B.dhall" ] ] _Interpolation_0 :: TestTree _Interpolation_0 = Test.Tasty.HUnit.testCase "Example #0" (do e <- Util.code " let name = \"John Doe\" \n\ \in let age = 21 \n\ \in \"My name is ${name} and my age is ${Natural/show age}\"\n" Util.assertNormalizesTo e "\"My name is John Doe and my age is 21\"" ) _Interpolation_1 :: TestTree _Interpolation_1 = Test.Tasty.HUnit.testCase "Example #1" (do e <- Util.code "'' \n\ \ for file in *; do \n\ \ echo \"Found ''${file}\"\n\ \ done \n\ \'' \n" Util.assertNormalized e ) _Functions_0 :: TestTree _Functions_0 = Test.Tasty.HUnit.testCase "Example #0" (do let text = "\\(n : Bool) -> [ n && True, n && False, n || True, n || False ]" makeBools <- Dhall.input Dhall.auto text makeBools True @?= Data.Vector.fromList [True,False,True,True] ) _Functions_1 :: TestTree _Functions_1 = Test.Tasty.HUnit.testCase "Example #1" (do let text = "λ(x : Bool) → λ(y : Bool) → x && y" makeBools <- Dhall.input Dhall.auto text makeBools True False @?= False ) data Example0 = Example0 { foo :: Bool, bar :: Bool } deriving (Generic, Inject) _Functions_2 :: TestTree _Functions_2 = Test.Tasty.HUnit.testCase "Example #2" (do f <- Dhall.input Dhall.auto "λ(r : { foo : Bool, bar : Bool }) → r.foo && r.bar" f (Example0 { foo = True, bar = False }) @?= False f (Example0 { foo = True, bar = True }) @?= True ) example :: Natural -> Text -> Text -> TestTree example n text0 text1 = Test.Tasty.HUnit.testCase ("Example #" <> show n) (Util.equivalent text0 text1) dhall-1.19.1/tests/TypeCheck.hs0000644000000000000000000001133113377175666014456 0ustar0000000000000000{-# LANGUAGE OverloadedStrings #-} module TypeCheck where import Data.Monoid (mempty, (<>)) import Data.Text (Text) import Dhall.Import (Imported) import Dhall.Parser (Src) import Dhall.TypeCheck (TypeError, X) import Test.Tasty (TestTree) import qualified Control.Exception import qualified Data.Text import qualified Dhall.Core import qualified Dhall.Import import qualified Dhall.Parser import qualified Dhall.TypeCheck import qualified Test.Tasty import qualified Test.Tasty.HUnit typecheckTests :: TestTree typecheckTests = Test.Tasty.testGroup "typecheck tests" [ preludeExamples , accessTypeChecks , should "allow type-valued fields in a record" "success/simple/fieldsAreTypes" , should "allow type-valued alternatives in a union" "success/simple/alternativesAreTypes" , should "allow anonymous functions in types to be judgmentally equal" "success/simple/anonymousFunctionsInTypes" , should "correctly handle α-equivalent merge alternatives" "success/simple/mergeEquivalence" , should "allow Kind variables" "success/simple/kindParameter" , shouldNotTypeCheck "combining records of terms and types" "failure/combineMixedRecords" , shouldNotTypeCheck "preferring a record of types over a record of terms" "failure/preferMixedRecords" , should "allow records of types of mixed kinds" "success/recordOfTypes" , should "allow Boehm-Berarducci-encoded records of types of mixed kinds" "success/encodedRecordOfTypes" , should "allow accessing a type from a record" "success/accessType" , should "allow accessing a type from a Boehm-Berarducci-encoded record" "success/accessEncodedType" , shouldNotTypeCheck "Hurkens' paradox" "failure/hurkensParadox" , should "allow accessing a constructor from a type stored inside a record" "success/simple/mixedFieldAccess" ] preludeExamples :: TestTree preludeExamples = Test.Tasty.testGroup "Prelude examples" [ should "Monoid" "./success/prelude/Monoid/00" , should "Monoid" "./success/prelude/Monoid/01" , should "Monoid" "./success/prelude/Monoid/02" , should "Monoid" "./success/prelude/Monoid/03" , should "Monoid" "./success/prelude/Monoid/04" , should "Monoid" "./success/prelude/Monoid/05" , should "Monoid" "./success/prelude/Monoid/06" , should "Monoid" "./success/prelude/Monoid/07" , should "Monoid" "./success/prelude/Monoid/08" , should "Monoid" "./success/prelude/Monoid/09" , should "Monoid" "./success/prelude/Monoid/10" ] accessTypeChecks :: TestTree accessTypeChecks = Test.Tasty.testGroup "typecheck access" [ should "record" "./success/simple/access/0" , should "record" "./success/simple/access/1" ] should :: Text -> Text -> TestTree should name basename = Test.Tasty.HUnit.testCase (Data.Text.unpack name) $ do let actualCode = "./tests/typecheck/" <> basename <> "A.dhall" let expectedCode = "./tests/typecheck/" <> basename <> "B.dhall" actualExpr <- case Dhall.Parser.exprFromText mempty actualCode of Left err -> Control.Exception.throwIO err Right expr -> return expr expectedExpr <- case Dhall.Parser.exprFromText mempty expectedCode of Left err -> Control.Exception.throwIO err Right expr -> return expr let annotatedExpr = Dhall.Core.Annot actualExpr expectedExpr resolvedExpr <- Dhall.Import.load annotatedExpr case Dhall.TypeCheck.typeOf resolvedExpr of Left err -> Control.Exception.throwIO err Right _ -> return () shouldNotTypeCheck :: Text -> Text -> TestTree shouldNotTypeCheck name basename = Test.Tasty.HUnit.testCase (Data.Text.unpack name) $ do let code = "./tests/typecheck/" <> basename <> ".dhall" expression <- case Dhall.Parser.exprFromText mempty code of Left exception -> Control.Exception.throwIO exception Right expression -> return expression let io :: IO Bool io = do _ <- Dhall.Import.load expression return True let handler :: Imported (TypeError Src X)-> IO Bool handler _ = return False typeChecked <- Control.Exception.handle handler io if typeChecked then fail (Data.Text.unpack code <> " should not have type-checked") else return () dhall-1.19.1/tests/Util.hs0000644000000000000000000000512613377175666013521 0ustar0000000000000000{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes #-} module Util ( code , codeWith , equivalent , normalize' , normalizeWith' , assertNormalizesTo , assertNormalizesToWith , assertNormalized , assertTypeChecks ) where import qualified Control.Exception import qualified Data.Functor import Data.Bifunctor (first) import Data.Text (Text) import qualified Dhall.Core import Dhall.Core (Expr, Normalizer) import qualified Dhall.Context import Dhall.Context (Context) import qualified Dhall.Import import qualified Dhall.Parser import Dhall.Parser (Src) import qualified Dhall.TypeCheck import Dhall.TypeCheck (X) import Test.Tasty.HUnit normalize' :: Expr Src X -> Text normalize' = Dhall.Core.pretty . Dhall.Core.normalize normalizeWith' :: Normalizer X -> Expr Src X -> Text normalizeWith' ctx = Dhall.Core.pretty . Dhall.Core.normalizeWith ctx code :: Text -> IO (Expr Src X) code = codeWith Dhall.Context.empty codeWith :: Context (Expr Src X) -> Text -> IO (Expr Src X) 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 case Dhall.TypeCheck.typeWith ctx expr1 of Left typeError -> Control.Exception.throwIO typeError Right _ -> return () return expr1 equivalent :: Text -> Text -> IO () equivalent text0 text1 = do expr0 <- fmap Dhall.Core.normalize (Util.code text0) :: IO (Expr X X) expr1 <- fmap Dhall.Core.normalize (Util.code text1) :: IO (Expr X X) assertEqual "Expressions are not equivalent" expr0 expr1 assertNormalizesTo :: Expr Src X -> 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 ctx e expected = do assertBool msg (not $ Dhall.Core.isNormalizedWith ctx (first (const ()) e)) normalizeWith' ctx e @?= expected where msg = "Given expression is already in normal form" assertNormalized :: Expr Src X -> IO () assertNormalized e = do assertBool msg1 (Dhall.Core.isNormalized e) assertEqual msg2 (normalize' e) (Dhall.Core.pretty e) where msg1 = "Expression was not in normal form" msg2 = "Normalization is not supposed to change the expression" assertTypeChecks :: Text -> IO () assertTypeChecks text = Data.Functor.void (code text) dhall-1.19.1/tests/format/0000755000000000000000000000000013377175666013534 5ustar0000000000000000dhall-1.19.1/tests/format/asciiA.dhall0000644000000000000000000000004213377175666015727 0ustar0000000000000000λ(a : Type) → ∀(b : a) → a dhall-1.19.1/tests/format/asciiB.dhall0000644000000000000000000000004213377175666015730 0ustar0000000000000000\(a : Type) -> forall (b : a) -> adhall-1.19.1/tests/format/doubleRoundA.dhall0000644000000000000000000000504113377175666017125 0ustar0000000000000000[ 1.0000000000000000 , 1.0000000000000001 , 1.0000000000000002 , 1.0000000000000003 , 1.0000000000000004 , 1.0000000000000005 , 1.0000000000000006 , 1.0000000000000007 , 1.0000000000000008 , 1.0000000000000009 , 1.0000000000000000e64 , 1.0000000000000001e64 , 1.0000000000000002e64 , 1.0000000000000003e64 , 1.0000000000000004e64 , 1.0000000000000005e64 , 1.0000000000000006e64 , 1.0000000000000007e64 , 1.0000000000000008e64 , 1.0000000000000009e64 , 1.0000000000000000e100 , 1.0000000000000001e100 , 1.0000000000000002e100 , 1.0000000000000003e100 , 1.0000000000000004e100 , 1.0000000000000005e100 , 1.0000000000000006e100 , 1.0000000000000007e100 , 1.0000000000000008e100 , 1.0000000000000009e100 , 179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497791.0 , 179769313486231560835325876058105298516207002341652166261661174625869553267292326574530099287946549246750631490335877017522087105926987962906277604735569213290190919152394180476217125334960946356387261286640198029037799514183602981511756283727771403830521483963923935633133642802139091669457927874464075218945.0 , 179769313486231560835325876058105298516207002341652166261661174625869553267292326574530099287946549246750631490335877017522087105926987962906277604735569213290190919152394180476217125334960946356387261286640198029037799514183602981511756283727771403830521483963923935633133642802139091669457927874464075218944.0 , -179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497791.0 , -179769313486231560835325876058105298516207002341652166261661174625869553267292326574530099287946549246750631490335877017522087105926987962906277604735569213290190919152394180476217125334960946356387261286640198029037799514183602981511756283727771403830521483963923935633133642802139091669457927874464075218945.0 , -179769313486231560835325876058105298516207002341652166261661174625869553267292326574530099287946549246750631490335877017522087105926987962906277604735569213290190919152394180476217125334960946356387261286640198029037799514183602981511756283727771403830521483963923935633133642802139091669457927874464075218944.0 ] dhall-1.19.1/tests/format/doubleRoundB.dhall0000644000000000000000000000141213377175666017124 0ustar0000000000000000[ 1.0 , 1.0 , 1.0000000000000002 , 1.0000000000000002 , 1.0000000000000004 , 1.0000000000000004 , 1.0000000000000007 , 1.0000000000000007 , 1.0000000000000009 , 1.0000000000000009 , 1.0e64 , 1.0000000000000002e64 , 1.0000000000000002e64 , 1.0000000000000003e64 , 1.0000000000000005e64 , 1.0000000000000005e64 , 1.0000000000000006e64 , 1.0000000000000008e64 , 1.0000000000000008e64 , 1.0000000000000009e64 , 1.0e100 , 1.0e100 , 1.0000000000000002e100 , 1.0000000000000002e100 , 1.0000000000000004e100 , 1.0000000000000004e100 , 1.0000000000000006e100 , 1.0000000000000008e100 , 1.0000000000000008e100 , 1.000000000000001e100 , 1.7976931348623157e308 , 1.7976931348623157e308 , 1.7976931348623155e308 , -1.7976931348623157e308 , -1.7976931348623157e308 , -1.7976931348623155e308 ]dhall-1.19.1/tests/format/emptyRecordA.dhall0000644000000000000000000000000413377175666017132 0ustar0000000000000000{=} dhall-1.19.1/tests/format/emptyRecordB.dhall0000644000000000000000000000000313377175666017132 0ustar0000000000000000{=}dhall-1.19.1/tests/format/escapeNumericLabelA.dhall0000644000000000000000000000001413377175666020361 0ustar0000000000000000{ `0` = 0 } dhall-1.19.1/tests/format/escapeNumericLabelB.dhall0000644000000000000000000000001313377175666020361 0ustar0000000000000000{ `0` = 0 }dhall-1.19.1/tests/format/escapeSingleQuotedOpenInterpolationA.dhall0000644000000000000000000000001013377175666024010 0ustar0000000000000000"\${\n" dhall-1.19.1/tests/format/escapeSingleQuotedOpenInterpolationB.dhall0000644000000000000000000000001213377175666024013 0ustar0000000000000000'' ''${ ''dhall-1.19.1/tests/format/fieldOrderA.dhall0000644000000000000000000000003013377175666016713 0ustar0000000000000000{ foo = 1, bar = True } dhall-1.19.1/tests/format/fieldOrderB.dhall0000644000000000000000000000002713377175666016722 0ustar0000000000000000{ foo = 1, bar = True }dhall-1.19.1/tests/format/ifThenElseA.dhall0000644000000000000000000000021613377175666016670 0ustar0000000000000000if 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 dhall-1.19.1/tests/format/ifThenElseB.dhall0000644000000000000000000000023713377175666016674 0ustar0000000000000000 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 8dhall-1.19.1/tests/format/importAccessA.dhall0000644000000000000000000000002513377175666017274 0ustar0000000000000000(./testImport).hello dhall-1.19.1/tests/format/importAccessB.dhall0000644000000000000000000000002413377175666017274 0ustar0000000000000000(./testImport).hellodhall-1.19.1/tests/format/importLines2A.dhall0000644000000000000000000000010313377175666017224 0ustar0000000000000000let _ = ./emptyRecordA.dhall in let _ = ./emptyRecordA.dhall in 123dhall-1.19.1/tests/format/importLines2B.dhall0000644000000000000000000000010313377175666017225 0ustar0000000000000000let _ = ./emptyRecordA.dhall in let _ = ./emptyRecordA.dhall in 123dhall-1.19.1/tests/format/importLinesA.dhall0000644000000000000000000000026613377175666017154 0ustar0000000000000000let _ = ./emptyRecordA.dhall let _ = ./emptyRecordA.dhall let _ = ./emptyRecordA.dhall let _ = ./emptyRecordA.dhall let _ = ./emptyRecordA.dhall let _ = ./emptyRecordA.dhall in 123 dhall-1.19.1/tests/format/importLinesB.dhall0000644000000000000000000000027313377175666017153 0ustar0000000000000000let _ = ./emptyRecordA.dhall let _ = ./emptyRecordA.dhall let _ = ./emptyRecordA.dhall let _ = ./emptyRecordA.dhall let _ = ./emptyRecordA.dhall let _ = ./emptyRecordA.dhall in 123dhall-1.19.1/tests/format/importSuffixA.dhall0000644000000000000000000000004213377175666017336 0ustar0000000000000000let a = env:AAA as Text in a dhall-1.19.1/tests/format/importSuffixB.dhall0000644000000000000000000000003413377175666017340 0ustar0000000000000000let a = env:AAA as Text in adhall-1.19.1/tests/format/largeExponentA.dhall0000644000000000000000000000002713377175666017455 0ustar0000000000000000[ 1.0, 1e100, 1e-100 ] dhall-1.19.1/tests/format/largeExponentB.dhall0000644000000000000000000000003213377175666017452 0ustar0000000000000000[ 1.0, 1.0e100, 1.0e-100 ]dhall-1.19.1/tests/format/multilineA.dhall0000644000000000000000000000001313377175666016637 0ustar0000000000000000"ABC\nDEF" dhall-1.19.1/tests/format/multilineB.dhall0000644000000000000000000000001413377175666016641 0ustar0000000000000000'' ABC DEF''dhall-1.19.1/tests/format/projectionOrderA.dhall0000644000000000000000000000002413377175666020007 0ustar0000000000000000e.{ foo, bar, baz } dhall-1.19.1/tests/format/projectionOrderB.dhall0000644000000000000000000000002313377175666020007 0ustar0000000000000000e.{ foo, bar, baz }dhall-1.19.1/tests/format/sha256PrintingA.dhall0000644000000000000000000000033413377175666017366 0ustar0000000000000000let replicate = https://raw.githubusercontent.com/dhall-lang/Prelude/c79c2bc3c46f129cc5b6d594ce298a381bcae92c/List/replicate sha256:cc856d59b63f7699881bdb8e4b1036ca4c0013827268040a50c1e1405f646a2c in replicate 5 dhall-1.19.1/tests/format/sha256PrintingB.dhall0000644000000000000000000000033313377175666017366 0ustar0000000000000000let replicate = https://raw.githubusercontent.com/dhall-lang/Prelude/c79c2bc3c46f129cc5b6d594ce298a381bcae92c/List/replicate sha256:cc856d59b63f7699881bdb8e4b1036ca4c0013827268040a50c1e1405f646a2c in replicate 5dhall-1.19.1/tests/format/unicodeA.dhall0000644000000000000000000000065613377175666016300 0ustar0000000000000000 λ(isActive : Bool) → { barLeftEnd = [ "┨" ] : Optional Text , barRightEnd = [ "┠" ] : Optional Text , separator = [ "┃" ] : Optional Text , alignment = < ToTheLeft = {=} | ToTheRight : {} | Centered : {} > : ./Alignment.dhall , barWidth = [] : Optional Natural , barSegments = [ "index", "command", "path", "title" ] } : ./Bar.dhall dhall-1.19.1/tests/format/unicodeB.dhall0000644000000000000000000000065513377175666016300 0ustar0000000000000000 λ(isActive : Bool) → { barLeftEnd = [ "┨" ] : Optional Text , barRightEnd = [ "┠" ] : Optional Text , separator = [ "┃" ] : Optional Text , alignment = < ToTheLeft = {=} | ToTheRight : {} | Centered : {} > : ./Alignment.dhall , barWidth = [] : Optional Natural , barSegments = [ "index", "command", "path", "title" ] } : ./Bar.dhalldhall-1.19.1/tests/import/0000755000000000000000000000000013377175666013556 5ustar0000000000000000dhall-1.19.1/tests/import/data/0000755000000000000000000000000013377175666014467 5ustar0000000000000000dhall-1.19.1/tests/import/data/fieldOrder/0000755000000000000000000000000013377175666016546 5ustar0000000000000000dhall-1.19.1/tests/import/data/fieldOrder/1.dhall0000644000000000000000000000003013377175666017705 0ustar0000000000000000{ foo = 1, bar = True } dhall-1.19.1/tests/import/data/fieldOrder/2.dhall0000644000000000000000000000003013377175666017706 0ustar0000000000000000{ bar = True, foo = 1 } dhall-1.19.1/tests/import/data/foo/0000755000000000000000000000000013377175666015252 5ustar0000000000000000dhall-1.19.1/tests/import/data/foo/bar/0000755000000000000000000000000013377175666016016 5ustar0000000000000000dhall-1.19.1/tests/import/data/foo/bar/a.dhall0000644000000000000000000000000313377175666017235 0ustar000000000000000042 dhall-1.19.1/tests/import/failure/0000755000000000000000000000000013377175666015205 5ustar0000000000000000dhall-1.19.1/tests/import/failure/alternativeEnv.dhall0000644000000000000000000000006713377175666021205 0ustar0000000000000000env:UNSET1 as Text ? env:UNSET2 ? missing ? env:UNSET3 dhall-1.19.1/tests/import/failure/alternativeEnvMissing.dhall0000644000000000000000000000002413377175666022530 0ustar0000000000000000env:UNSET ? missing dhall-1.19.1/tests/import/failure/missing.dhall0000644000000000000000000000001013377175666017653 0ustar0000000000000000missing dhall-1.19.1/tests/import/success/0000755000000000000000000000000013377175666015226 5ustar0000000000000000dhall-1.19.1/tests/import/success/alternativeEnvNaturalA.dhall0000644000000000000000000000007313377175666022653 0ustar0000000000000000env:UNSET1 as Text ? env:UNSET2 ? missing ? env:UNSET3 ? 2 dhall-1.19.1/tests/import/success/alternativeEnvNaturalB.dhall0000644000000000000000000000000213377175666022644 0ustar00000000000000002 dhall-1.19.1/tests/import/success/alternativeEnvSimpleA.dhall0000644000000000000000000000001613377175666022473 0ustar0000000000000000env:UNSET ? 3 dhall-1.19.1/tests/import/success/alternativeEnvSimpleB.dhall0000644000000000000000000000000213377175666022467 0ustar00000000000000003 dhall-1.19.1/tests/import/success/alternativeNaturalA.dhall0000644000000000000000000000001413377175666022175 0ustar00000000000000004 ? missing dhall-1.19.1/tests/import/success/alternativeNaturalB.dhall0000644000000000000000000000000213377175666022173 0ustar00000000000000004 dhall-1.19.1/tests/import/success/fieldOrderA.dhall0000644000000000000000000000035613377175666020420 0ustar0000000000000000{ example0 = ./../data/fieldOrder/1.dhall sha256:4a7866b88389e18cf481b525544fd7903325252faf3a86c8fdc981298c788a9b , example1 = ./../data/fieldOrder/2.dhall sha256:4a7866b88389e18cf481b525544fd7903325252faf3a86c8fdc981298c788a9b } dhall-1.19.1/tests/import/success/fieldOrderB.dhall0000644000000000000000000000011313377175666020410 0ustar0000000000000000{ example0 = { bar = True, foo = 1 }, example1 = { bar = True, foo = 1 } } dhall-1.19.1/tests/import/success/issue553A.dhall0000644000000000000000000000010313377175666017714 0ustar0000000000000000 let T = < A : {} | B : {} > in let t = constructors T in t dhall-1.19.1/tests/import/success/issue553B.dhall0000644000000000000000000000013213377175666017717 0ustar0000000000000000./issue553A.dhall sha256:6fb582c043889dd5a4c97176f8a58d2633252b5374cb71e288b93bc3757f9643 dhall-1.19.1/tests/import/success/relative.dhall0000644000000000000000000000013013377175666020041 0ustar0000000000000000-- This file assumes its base directory is actually ./data/foo/bar/ ./a.dhall : Natural dhall-1.19.1/tests/lint/0000755000000000000000000000000013377175666013212 5ustar0000000000000000dhall-1.19.1/tests/lint/success/0000755000000000000000000000000013377175666014662 5ustar0000000000000000dhall-1.19.1/tests/lint/success/multiletA.dhall0000644000000000000000000000161613377175666017634 0ustar0000000000000000-- example0.dhall let Person : Type = ∀(Person : Type) → ∀(MakePerson : { children : List Person, name : Text } → Person) → Person let example : Person = λ(Person : Type) → λ(MakePerson : { children : List Person, name : Text } → Person) → MakePerson { children = [ MakePerson { children = [] : List Person, name = "Mary" } , MakePerson { children = [] : List Person, name = "Jane" } ] , name = "John" } let everybody : Person → List Text = let concat = http://prelude.dhall-lang.org/List/concat 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 dhall-1.19.1/tests/lint/success/multiletB.dhall0000644000000000000000000000161613377175666017635 0ustar0000000000000000-- example0.dhall let Person : Type = ∀(Person : Type) → ∀(MakePerson : { children : List Person, name : Text } → Person) → Person let example : Person = λ(Person : Type) → λ(MakePerson : { children : List Person, name : Text } → Person) → MakePerson { children = [ MakePerson { children = [] : List Person, name = "Mary" } , MakePerson { children = [] : List Person, name = "Jane" } ] , name = "John" } let everybody : Person → List Text = let concat = http://prelude.dhall-lang.org/List/concat 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 dhall-1.19.1/tests/normalization/0000755000000000000000000000000013377175666015132 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/0000755000000000000000000000000013377175666016602 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/remoteSystemsA.dhall0000644000000000000000000000245713377175666022604 0ustar0000000000000000let Text/concatMap = (./../../../Prelude/package.dhall).`Text`.concatMap let Text/concatSep = (./../../../Prelude/package.dhall).`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 = Optional/fold Text row.user Text (λ(user : Text) → "${user}@${row.host}") row.host 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-1.19.1/tests/normalization/success/remoteSystemsB.dhall0000644000000000000000000000417613377175666022605 0ustar0000000000000000λ(xs : List { cores : Natural, host : Text, key : Text, mandatoryFeatures : List Text, platforms : List Text, speedFactor : Natural, supportedFeatures : List Text, user : Optional Text }) → List/fold { cores : Natural, host : Text, key : Text, mandatoryFeatures : List Text, platforms : List Text, speedFactor : Natural, supportedFeatures : List Text, user : Optional Text } xs Text (λ(x : { cores : Natural, host : Text, key : Text, mandatoryFeatures : List Text, platforms : List Text, speedFactor : Natural, supportedFeatures : List Text, user : Optional Text }) → λ(y : Text) → "${Optional/fold Text x.user Text (λ(user : Text) → "${user}@${x.host}") x.host} ${merge { Empty = λ(_ : {}) → "", NonEmpty = λ(result : Text) → result } (List/fold Text x.platforms < Empty : {} | NonEmpty : Text > (λ(element : Text) → λ(status : < Empty : {} | NonEmpty : Text >) → merge { Empty = λ(_ : {}) → < NonEmpty = element | Empty : {} >, NonEmpty = λ(result : Text) → < NonEmpty = element ++ "," ++ result | Empty : {} > } status : < Empty : {} | NonEmpty : Text >) < Empty = {=} | NonEmpty : Text >) : Text} ${x.key} ${Integer/show (Natural/toInteger x.cores)} ${Integer/show (Natural/toInteger x.speedFactor)} ${merge { Empty = λ(_ : {}) → "", NonEmpty = λ(result : Text) → result } (List/fold Text x.supportedFeatures < Empty : {} | NonEmpty : Text > (λ(element : Text) → λ(status : < Empty : {} | NonEmpty : Text >) → merge { Empty = λ(_ : {}) → < NonEmpty = element | Empty : {} >, NonEmpty = λ(result : Text) → < NonEmpty = element ++ "," ++ result | Empty : {} > } status : < Empty : {} | NonEmpty : Text >) < Empty = {=} | NonEmpty : Text >) : Text} ${merge { Empty = λ(_ : {}) → "", NonEmpty = λ(result : Text) → result } (List/fold Text x.mandatoryFeatures < Empty : {} | NonEmpty : Text > (λ(element : Text) → λ(status : < Empty : {} | NonEmpty : Text >) → merge { Empty = λ(_ : {}) → < NonEmpty = element | Empty : {} >, NonEmpty = λ(result : Text) → < NonEmpty = element ++ "," ++ result | Empty : {} > } status : < Empty : {} | NonEmpty : Text >) < Empty = {=} | NonEmpty : Text >) : Text}\n" ++ y) "" dhall-1.19.1/tests/normalization/success/haskell-tutorial/0000755000000000000000000000000013377175666022066 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/haskell-tutorial/access/0000755000000000000000000000000013377175666023327 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/haskell-tutorial/access/0A.dhall0000644000000000000000000000002013377175666024565 0ustar0000000000000000{ x = "foo" }.x dhall-1.19.1/tests/normalization/success/haskell-tutorial/access/0B.dhall0000644000000000000000000000000613377175666024572 0ustar0000000000000000"foo" dhall-1.19.1/tests/normalization/success/haskell-tutorial/access/1A.dhall0000644000000000000000000000004313377175666024573 0ustar0000000000000000< Foo : Text | Bar : Natural >.Foo dhall-1.19.1/tests/normalization/success/haskell-tutorial/access/1B.dhall0000644000000000000000000000006113377175666024574 0ustar0000000000000000λ(Foo : Text) → < Foo = Foo | Bar : Natural > dhall-1.19.1/tests/normalization/success/haskell-tutorial/combineTypes/0000755000000000000000000000000013377175666024527 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/haskell-tutorial/combineTypes/0A.dhall0000644000000000000000000000010513377175666025771 0ustar0000000000000000{ foo : { bar : Text } } ⩓ { foo : { baz : Bool }, qux : Integer } dhall-1.19.1/tests/normalization/success/haskell-tutorial/combineTypes/0B.dhall0000644000000000000000000000006413377175666025776 0ustar0000000000000000{ foo : { bar : Text, baz : Bool }, qux : Integer } dhall-1.19.1/tests/normalization/success/haskell-tutorial/combineTypes/1A.dhall0000644000000000000000000000010613377175666025773 0ustar0000000000000000{ foo : { bar : Text } } //\\ { foo : { baz : Bool }, qux : Integer } dhall-1.19.1/tests/normalization/success/haskell-tutorial/combineTypes/1B.dhall0000644000000000000000000000006413377175666025777 0ustar0000000000000000{ foo : { bar : Text, baz : Bool }, qux : Integer } dhall-1.19.1/tests/normalization/success/haskell-tutorial/prefer/0000755000000000000000000000000013377175666023351 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/haskell-tutorial/prefer/0A.dhall0000644000000000000000000000005313377175666024615 0ustar0000000000000000{ foo = 1, bar = "ABC" } // { baz = True } dhall-1.19.1/tests/normalization/success/haskell-tutorial/prefer/0B.dhall0000644000000000000000000000004513377175666024617 0ustar0000000000000000{ bar = "ABC", baz = True, foo = 1 } dhall-1.19.1/tests/normalization/success/haskell-tutorial/projection/0000755000000000000000000000000013377175666024242 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/haskell-tutorial/projection/0A.dhall0000644000000000000000000000005013377175666025503 0ustar0000000000000000{ x = 1, y = True, z = "ABC" }.{ x, y } dhall-1.19.1/tests/normalization/success/haskell-tutorial/projection/0B.dhall0000644000000000000000000000002413377175666025505 0ustar0000000000000000{ x = 1, y = True } dhall-1.19.1/tests/normalization/success/prelude/0000755000000000000000000000000013377175666020242 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Bool/0000755000000000000000000000000013377175666021135 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Bool/and/0000755000000000000000000000000013377175666021677 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Bool/and/0A.dhall0000644000000000000000000000011313377175666023140 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Bool`.and [ True, False, True ] dhall-1.19.1/tests/normalization/success/prelude/Bool/and/0B.dhall0000644000000000000000000000000613377175666023142 0ustar0000000000000000False dhall-1.19.1/tests/normalization/success/prelude/Bool/and/1A.dhall0000644000000000000000000000010613377175666023143 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Bool`.and ([] : List Bool) dhall-1.19.1/tests/normalization/success/prelude/Bool/and/1B.dhall0000644000000000000000000000000513377175666023142 0ustar0000000000000000True dhall-1.19.1/tests/normalization/success/prelude/Bool/build/0000755000000000000000000000000013377175666022234 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Bool/build/0A.dhall0000644000000000000000000000017413377175666023504 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Bool`.build (λ(bool : Type) → λ(true : bool) → λ(false : bool) → true) dhall-1.19.1/tests/normalization/success/prelude/Bool/build/0B.dhall0000644000000000000000000000000513377175666023476 0ustar0000000000000000True dhall-1.19.1/tests/normalization/success/prelude/Bool/build/1A.dhall0000644000000000000000000000017513377175666023506 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Bool`.build (λ(bool : Type) → λ(true : bool) → λ(false : bool) → false) dhall-1.19.1/tests/normalization/success/prelude/Bool/build/1B.dhall0000644000000000000000000000000613377175666023500 0ustar0000000000000000False dhall-1.19.1/tests/normalization/success/prelude/Bool/even/0000755000000000000000000000000013377175666022072 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Bool/even/0A.dhall0000644000000000000000000000011513377175666023335 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Bool`.even [ False, True, False ] dhall-1.19.1/tests/normalization/success/prelude/Bool/even/0B.dhall0000644000000000000000000000000513377175666023334 0ustar0000000000000000True dhall-1.19.1/tests/normalization/success/prelude/Bool/even/1A.dhall0000644000000000000000000000010613377175666023336 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Bool`.even [ False, True ] dhall-1.19.1/tests/normalization/success/prelude/Bool/even/1B.dhall0000644000000000000000000000000613377175666023336 0ustar0000000000000000False dhall-1.19.1/tests/normalization/success/prelude/Bool/even/2A.dhall0000644000000000000000000000010013377175666023331 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Bool`.even [ False ] dhall-1.19.1/tests/normalization/success/prelude/Bool/even/2B.dhall0000644000000000000000000000000613377175666023337 0ustar0000000000000000False dhall-1.19.1/tests/normalization/success/prelude/Bool/even/3A.dhall0000644000000000000000000000010713377175666023341 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Bool`.even ([] : List Bool) dhall-1.19.1/tests/normalization/success/prelude/Bool/even/3B.dhall0000644000000000000000000000000513377175666023337 0ustar0000000000000000True dhall-1.19.1/tests/normalization/success/prelude/Bool/fold/0000755000000000000000000000000013377175666022061 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Bool/fold/0A.dhall0000644000000000000000000000010713377175666023325 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Bool`.fold True Natural 0 1 dhall-1.19.1/tests/normalization/success/prelude/Bool/fold/0B.dhall0000644000000000000000000000000213377175666023320 0ustar00000000000000000 dhall-1.19.1/tests/normalization/success/prelude/Bool/fold/1A.dhall0000644000000000000000000000011013377175666023320 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Bool`.fold False Natural 0 1 dhall-1.19.1/tests/normalization/success/prelude/Bool/fold/1B.dhall0000644000000000000000000000000213377175666023321 0ustar00000000000000001 dhall-1.19.1/tests/normalization/success/prelude/Bool/not/0000755000000000000000000000000013377175666021735 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Bool/not/0A.dhall0000644000000000000000000000007213377175666023202 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Bool`.not True dhall-1.19.1/tests/normalization/success/prelude/Bool/not/0B.dhall0000644000000000000000000000000613377175666023200 0ustar0000000000000000False dhall-1.19.1/tests/normalization/success/prelude/Bool/not/1A.dhall0000644000000000000000000000007313377175666023204 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Bool`.not False dhall-1.19.1/tests/normalization/success/prelude/Bool/not/1B.dhall0000644000000000000000000000000513377175666023200 0ustar0000000000000000True dhall-1.19.1/tests/normalization/success/prelude/Bool/odd/0000755000000000000000000000000013377175666021703 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Bool/odd/0A.dhall0000644000000000000000000000011313377175666023144 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Bool`.odd [ True, False, True ] dhall-1.19.1/tests/normalization/success/prelude/Bool/odd/0B.dhall0000644000000000000000000000000613377175666023146 0ustar0000000000000000False dhall-1.19.1/tests/normalization/success/prelude/Bool/odd/1A.dhall0000644000000000000000000000010513377175666023146 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Bool`.odd [ True, False ] dhall-1.19.1/tests/normalization/success/prelude/Bool/odd/1B.dhall0000644000000000000000000000000513377175666023146 0ustar0000000000000000True dhall-1.19.1/tests/normalization/success/prelude/Bool/odd/2A.dhall0000644000000000000000000000007613377175666023156 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Bool`.odd [ True ] dhall-1.19.1/tests/normalization/success/prelude/Bool/odd/2B.dhall0000644000000000000000000000000513377175666023147 0ustar0000000000000000True dhall-1.19.1/tests/normalization/success/prelude/Bool/odd/3A.dhall0000644000000000000000000000010613377175666023151 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Bool`.odd ([] : List Bool) dhall-1.19.1/tests/normalization/success/prelude/Bool/odd/3B.dhall0000644000000000000000000000000613377175666023151 0ustar0000000000000000False dhall-1.19.1/tests/normalization/success/prelude/Bool/or/0000755000000000000000000000000013377175666021555 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Bool/or/0A.dhall0000644000000000000000000000011213377175666023015 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Bool`.or [ True, False, True ] dhall-1.19.1/tests/normalization/success/prelude/Bool/or/0B.dhall0000644000000000000000000000000513377175666023017 0ustar0000000000000000True dhall-1.19.1/tests/normalization/success/prelude/Bool/or/1A.dhall0000644000000000000000000000010513377175666023020 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Bool`.or ([] : List Bool) dhall-1.19.1/tests/normalization/success/prelude/Bool/or/1B.dhall0000644000000000000000000000000613377175666023021 0ustar0000000000000000False dhall-1.19.1/tests/normalization/success/prelude/Bool/show/0000755000000000000000000000000013377175666022115 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Bool/show/0A.dhall0000644000000000000000000000007313377175666023363 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Bool`.show True dhall-1.19.1/tests/normalization/success/prelude/Bool/show/0B.dhall0000644000000000000000000000000713377175666023361 0ustar0000000000000000"True" dhall-1.19.1/tests/normalization/success/prelude/Bool/show/1A.dhall0000644000000000000000000000007413377175666023365 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Bool`.show False dhall-1.19.1/tests/normalization/success/prelude/Bool/show/1B.dhall0000644000000000000000000000001013377175666023354 0ustar0000000000000000"False" dhall-1.19.1/tests/normalization/success/prelude/Double/0000755000000000000000000000000013377175666021454 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Double/show/0000755000000000000000000000000013377175666022434 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Double/show/0A.dhall0000644000000000000000000000007513377175666023704 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Double`.show -3.1 dhall-1.19.1/tests/normalization/success/prelude/Double/show/0B.dhall0000644000000000000000000000000713377175666023700 0ustar0000000000000000"-3.1" dhall-1.19.1/tests/normalization/success/prelude/Double/show/1A.dhall0000644000000000000000000000007413377175666023704 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Double`.show 0.4 dhall-1.19.1/tests/normalization/success/prelude/Double/show/1B.dhall0000644000000000000000000000000613377175666023700 0ustar0000000000000000"0.4" dhall-1.19.1/tests/normalization/success/prelude/Integer/0000755000000000000000000000000013377175666021637 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Integer/show/0000755000000000000000000000000013377175666022617 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Integer/show/0A.dhall0000644000000000000000000000007413377175666024066 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Integer`.show -3 dhall-1.19.1/tests/normalization/success/prelude/Integer/show/0B.dhall0000644000000000000000000000000513377175666024061 0ustar0000000000000000"-3" dhall-1.19.1/tests/normalization/success/prelude/Integer/show/1A.dhall0000644000000000000000000000007413377175666024067 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Integer`.show +0 dhall-1.19.1/tests/normalization/success/prelude/Integer/show/1B.dhall0000644000000000000000000000000513377175666024062 0ustar0000000000000000"+0" dhall-1.19.1/tests/normalization/success/prelude/Integer/toDouble/0000755000000000000000000000000013377175666023414 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Integer/toDouble/0A.dhall0000644000000000000000000000010013377175666024651 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Integer`.toDouble -3 dhall-1.19.1/tests/normalization/success/prelude/Integer/toDouble/0B.dhall0000644000000000000000000000000513377175666024656 0ustar0000000000000000-3.0 dhall-1.19.1/tests/normalization/success/prelude/Integer/toDouble/1A.dhall0000644000000000000000000000010013377175666024652 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Integer`.toDouble +2 dhall-1.19.1/tests/normalization/success/prelude/Integer/toDouble/1B.dhall0000644000000000000000000000000413377175666024656 0ustar00000000000000002.0 dhall-1.19.1/tests/normalization/success/prelude/List/0000755000000000000000000000000013377175666021155 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/List/all/0000755000000000000000000000000013377175666021725 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/List/all/0A.dhall0000644000000000000000000000012613377175666023172 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`List`.all Natural Natural/even [ 2, 3, 5 ] dhall-1.19.1/tests/normalization/success/prelude/List/all/0B.dhall0000644000000000000000000000000613377175666023170 0ustar0000000000000000False dhall-1.19.1/tests/normalization/success/prelude/List/all/1A.dhall0000644000000000000000000000013613377175666023174 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`List`.all Natural Natural/even ([] : List Natural) dhall-1.19.1/tests/normalization/success/prelude/List/all/1B.dhall0000644000000000000000000000000513377175666023170 0ustar0000000000000000True dhall-1.19.1/tests/normalization/success/prelude/List/any/0000755000000000000000000000000013377175666021744 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/List/any/0A.dhall0000644000000000000000000000012613377175666023211 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`List`.any Natural Natural/even [ 2, 3, 5 ] dhall-1.19.1/tests/normalization/success/prelude/List/any/0B.dhall0000644000000000000000000000000513377175666023206 0ustar0000000000000000True dhall-1.19.1/tests/normalization/success/prelude/List/any/1A.dhall0000644000000000000000000000013613377175666023213 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`List`.any Natural Natural/even ([] : List Natural) dhall-1.19.1/tests/normalization/success/prelude/List/any/1B.dhall0000644000000000000000000000000613377175666023210 0ustar0000000000000000False dhall-1.19.1/tests/normalization/success/prelude/List/build/0000755000000000000000000000000013377175666022254 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/List/build/0A.dhall0000644000000000000000000000025113377175666023520 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`List`.build Text ( λ(list : Type) → λ(cons : Text → list → list) → λ(nil : list) → cons "ABC" (cons "DEF" nil) ) dhall-1.19.1/tests/normalization/success/prelude/List/build/0B.dhall0000644000000000000000000000002113377175666023514 0ustar0000000000000000[ "ABC", "DEF" ] dhall-1.19.1/tests/normalization/success/prelude/List/build/1A.dhall0000644000000000000000000000022113377175666023516 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`List`.build Text ( λ(list : Type) → λ(cons : Text → list → list) → λ(nil : list) → nil ) dhall-1.19.1/tests/normalization/success/prelude/List/build/1B.dhall0000644000000000000000000000001713377175666023522 0ustar0000000000000000[] : List Text dhall-1.19.1/tests/normalization/success/prelude/List/concat/0000755000000000000000000000000013377175666022424 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/List/concat/0A.dhall0000644000000000000000000000015413377175666023672 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`List`.concat Natural [ [ 0, 1, 2 ] , [ 3, 4 ] , [ 5, 6, 7, 8 ] ] dhall-1.19.1/tests/normalization/success/prelude/List/concat/0B.dhall0000644000000000000000000000003613377175666023672 0ustar0000000000000000[ 0, 1, 2, 3, 4, 5, 6, 7, 8 ] dhall-1.19.1/tests/normalization/success/prelude/List/concat/1A.dhall0000644000000000000000000000017613377175666023677 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`List`.concat Natural [ [] : List Natural , [] : List Natural , [] : List Natural ] dhall-1.19.1/tests/normalization/success/prelude/List/concat/1B.dhall0000644000000000000000000000002213377175666023666 0ustar0000000000000000[] : List Natural dhall-1.19.1/tests/normalization/success/prelude/List/concatMap/0000755000000000000000000000000013377175666023062 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/List/concatMap/0A.dhall0000644000000000000000000000016613377175666024333 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`List`.concatMap Natural Natural (λ(n : Natural) → [ n, n ]) [ 2, 3, 5 ] dhall-1.19.1/tests/normalization/success/prelude/List/concatMap/0B.dhall0000644000000000000000000000002513377175666024326 0ustar0000000000000000[ 2, 2, 3, 3, 5, 5 ] dhall-1.19.1/tests/normalization/success/prelude/List/concatMap/1A.dhall0000644000000000000000000000017613377175666024335 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`List`.concatMap Natural Natural (λ(n : Natural) → [ n, n ]) ([] : List Natural) dhall-1.19.1/tests/normalization/success/prelude/List/concatMap/1B.dhall0000644000000000000000000000002213377175666024324 0ustar0000000000000000[] : List Natural dhall-1.19.1/tests/normalization/success/prelude/List/filter/0000755000000000000000000000000013377175666022442 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/List/filter/0A.dhall0000644000000000000000000000013113377175666023703 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`List`.filter Natural Natural/even [ 2, 3, 5 ] dhall-1.19.1/tests/normalization/success/prelude/List/filter/0B.dhall0000644000000000000000000000000613377175666023705 0ustar0000000000000000[ 2 ] dhall-1.19.1/tests/normalization/success/prelude/List/filter/1A.dhall0000644000000000000000000000013013377175666023703 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`List`.filter Natural Natural/odd [ 2, 3, 5 ] dhall-1.19.1/tests/normalization/success/prelude/List/filter/1B.dhall0000644000000000000000000000001113377175666023702 0ustar0000000000000000[ 3, 5 ] dhall-1.19.1/tests/normalization/success/prelude/List/fold/0000755000000000000000000000000013377175666022101 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/List/fold/0A.dhall0000644000000000000000000000020413377175666023343 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`List`.fold Natural [ 2, 3, 5 ] Natural (λ(x : Natural) → λ(y : Natural) → x + y) 0 dhall-1.19.1/tests/normalization/success/prelude/List/fold/0B.dhall0000644000000000000000000000000313377175666023341 0ustar000000000000000010 dhall-1.19.1/tests/normalization/success/prelude/List/fold/1A.dhall0000644000000000000000000000025013377175666023345 0ustar0000000000000000 λ(nil : Natural) → (../../../../../../Prelude/package.dhall).`List`.fold Natural [ 2, 3, 5 ] Natural (λ(x : Natural) → λ(y : Natural) → x + y) nil dhall-1.19.1/tests/normalization/success/prelude/List/fold/1B.dhall0000644000000000000000000000005213377175666023346 0ustar0000000000000000λ(nil : Natural) → 2 + (3 + (5 + nil)) dhall-1.19.1/tests/normalization/success/prelude/List/fold/2A.dhall0000644000000000000000000000025213377175666023350 0ustar0000000000000000 λ(list : Type) → λ(cons : Natural → list → list) → λ(nil : list) → (../../../../../../Prelude/package.dhall).`List`.fold Natural [ 2, 3, 5 ] list cons nil dhall-1.19.1/tests/normalization/success/prelude/List/fold/2B.dhall0000644000000000000000000000015713377175666023355 0ustar0000000000000000 λ(list : Type) → λ(cons : Natural → list → list) → λ(nil : list) → cons 2 (cons 3 (cons 5 nil)) dhall-1.19.1/tests/normalization/success/prelude/List/generate/0000755000000000000000000000000013377175666022747 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/List/generate/0A.dhall0000644000000000000000000000011613377175666024213 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`List`.generate 5 Bool Natural/even dhall-1.19.1/tests/normalization/success/prelude/List/generate/0B.dhall0000644000000000000000000000004313377175666024213 0ustar0000000000000000[ True, False, True, False, True ] dhall-1.19.1/tests/normalization/success/prelude/List/generate/1A.dhall0000644000000000000000000000011613377175666024214 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`List`.generate 0 Bool Natural/even dhall-1.19.1/tests/normalization/success/prelude/List/generate/1B.dhall0000644000000000000000000000001713377175666024215 0ustar0000000000000000[] : List Bool dhall-1.19.1/tests/normalization/success/prelude/List/head/0000755000000000000000000000000013377175666022056 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/List/head/0A.dhall0000644000000000000000000000011213377175666023316 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`List`.head Natural [ 0, 1, 2 ] dhall-1.19.1/tests/normalization/success/prelude/List/head/0B.dhall0000644000000000000000000000000713377175666023322 0ustar0000000000000000Some 0 dhall-1.19.1/tests/normalization/success/prelude/List/head/1A.dhall0000644000000000000000000000012213377175666023320 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`List`.head Natural ([] : List Natural) dhall-1.19.1/tests/normalization/success/prelude/List/head/1B.dhall0000644000000000000000000000001513377175666023322 0ustar0000000000000000None Natural dhall-1.19.1/tests/normalization/success/prelude/List/indexed/0000755000000000000000000000000013377175666022575 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/List/indexed/0A.dhall0000644000000000000000000000012413377175666024040 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`List`.indexed Bool [ True, False, True ] dhall-1.19.1/tests/normalization/success/prelude/List/indexed/0B.dhall0000644000000000000000000000013513377175666024043 0ustar0000000000000000[ { index = 0, value = True } , { index = 1, value = False } , { index = 2, value = True } ] dhall-1.19.1/tests/normalization/success/prelude/List/indexed/1A.dhall0000644000000000000000000000011713377175666024043 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`List`.indexed Bool ([] : List Bool) dhall-1.19.1/tests/normalization/success/prelude/List/indexed/1B.dhall0000644000000000000000000000005413377175666024044 0ustar0000000000000000[] : List { index : Natural, value : Bool } dhall-1.19.1/tests/normalization/success/prelude/List/iterate/0000755000000000000000000000000013377175666022612 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/List/iterate/0A.dhall0000644000000000000000000000014213377175666024055 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`List`.iterate 10 Natural (λ(x : Natural) → x * 2) 1 dhall-1.19.1/tests/normalization/success/prelude/List/iterate/0B.dhall0000644000000000000000000000005213377175666024056 0ustar0000000000000000[ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512 ] dhall-1.19.1/tests/normalization/success/prelude/List/iterate/1A.dhall0000644000000000000000000000014113377175666024055 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`List`.iterate 0 Natural (λ(x : Natural) → x * 2) 1 dhall-1.19.1/tests/normalization/success/prelude/List/iterate/1B.dhall0000644000000000000000000000002213377175666024054 0ustar0000000000000000[] : List Natural dhall-1.19.1/tests/normalization/success/prelude/List/last/0000755000000000000000000000000013377175666022120 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/List/last/0A.dhall0000644000000000000000000000011213377175666023360 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`List`.last Natural [ 0, 1, 2 ] dhall-1.19.1/tests/normalization/success/prelude/List/last/0B.dhall0000644000000000000000000000000713377175666023364 0ustar0000000000000000Some 2 dhall-1.19.1/tests/normalization/success/prelude/List/last/1A.dhall0000644000000000000000000000012213377175666023362 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`List`.last Natural ([] : List Natural) dhall-1.19.1/tests/normalization/success/prelude/List/last/1B.dhall0000644000000000000000000000001513377175666023364 0ustar0000000000000000None Natural dhall-1.19.1/tests/normalization/success/prelude/List/length/0000755000000000000000000000000013377175666022436 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/List/length/0A.dhall0000644000000000000000000000011413377175666023700 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`List`.length Natural [ 0, 1, 2 ] dhall-1.19.1/tests/normalization/success/prelude/List/length/0B.dhall0000644000000000000000000000000213377175666023675 0ustar00000000000000003 dhall-1.19.1/tests/normalization/success/prelude/List/length/1A.dhall0000644000000000000000000000012413377175666023702 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`List`.length Natural ([] : List Natural) dhall-1.19.1/tests/normalization/success/prelude/List/length/1B.dhall0000644000000000000000000000000213377175666023676 0ustar00000000000000000 dhall-1.19.1/tests/normalization/success/prelude/List/map/0000755000000000000000000000000013377175666021732 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/List/map/0A.dhall0000644000000000000000000000013313377175666023175 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`List`.map Natural Bool Natural/even [ 2, 3, 5 ] dhall-1.19.1/tests/normalization/success/prelude/List/map/0B.dhall0000644000000000000000000000002713377175666023200 0ustar0000000000000000[ True, False, False ] dhall-1.19.1/tests/normalization/success/prelude/List/map/1A.dhall0000644000000000000000000000014313377175666023177 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`List`.map Natural Bool Natural/even ([] : List Natural) dhall-1.19.1/tests/normalization/success/prelude/List/map/1B.dhall0000644000000000000000000000001713377175666023200 0ustar0000000000000000[] : List Bool dhall-1.19.1/tests/normalization/success/prelude/List/null/0000755000000000000000000000000013377175666022127 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/List/null/0A.dhall0000644000000000000000000000011213377175666023367 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`List`.null Natural [ 0, 1, 2 ] dhall-1.19.1/tests/normalization/success/prelude/List/null/0B.dhall0000644000000000000000000000000613377175666023372 0ustar0000000000000000False dhall-1.19.1/tests/normalization/success/prelude/List/null/1A.dhall0000644000000000000000000000012213377175666023371 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`List`.null Natural ([] : List Natural) dhall-1.19.1/tests/normalization/success/prelude/List/null/1B.dhall0000644000000000000000000000000513377175666023372 0ustar0000000000000000True dhall-1.19.1/tests/normalization/success/prelude/List/replicate/0000755000000000000000000000000013377175666023125 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/List/replicate/0A.dhall0000644000000000000000000000010713377175666024371 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`List`.replicate 9 Natural 1 dhall-1.19.1/tests/normalization/success/prelude/List/replicate/0B.dhall0000644000000000000000000000003613377175666024373 0ustar0000000000000000[ 1, 1, 1, 1, 1, 1, 1, 1, 1 ] dhall-1.19.1/tests/normalization/success/prelude/List/replicate/1A.dhall0000644000000000000000000000010713377175666024372 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`List`.replicate 0 Natural 1 dhall-1.19.1/tests/normalization/success/prelude/List/replicate/1B.dhall0000644000000000000000000000002213377175666024367 0ustar0000000000000000[] : List Natural dhall-1.19.1/tests/normalization/success/prelude/List/reverse/0000755000000000000000000000000013377175666022630 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/List/reverse/0A.dhall0000644000000000000000000000011513377175666024073 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`List`.reverse Natural [ 0, 1, 2 ] dhall-1.19.1/tests/normalization/success/prelude/List/reverse/0B.dhall0000644000000000000000000000001413377175666024072 0ustar0000000000000000[ 2, 1, 0 ] dhall-1.19.1/tests/normalization/success/prelude/List/reverse/1A.dhall0000644000000000000000000000012513377175666024075 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`List`.reverse Natural ([] : List Natural) dhall-1.19.1/tests/normalization/success/prelude/List/reverse/1B.dhall0000644000000000000000000000002213377175666024072 0ustar0000000000000000[] : List Natural dhall-1.19.1/tests/normalization/success/prelude/List/shifted/0000755000000000000000000000000013377175666022603 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/List/shifted/0A.dhall0000644000000000000000000000055713377175666024060 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`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-1.19.1/tests/normalization/success/prelude/List/shifted/0B.dhall0000644000000000000000000000042313377175666024051 0ustar0000000000000000[ { 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-1.19.1/tests/normalization/success/prelude/List/shifted/1A.dhall0000644000000000000000000000016313377175666024052 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`List`.shifted Bool ([] : List (List { index : Natural, value : Bool })) dhall-1.19.1/tests/normalization/success/prelude/List/shifted/1B.dhall0000644000000000000000000000005413377175666024052 0ustar0000000000000000[] : List { index : Natural, value : Bool } dhall-1.19.1/tests/normalization/success/prelude/List/unzip/0000755000000000000000000000000013377175666022322 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/List/unzip/0A.dhall0000644000000000000000000000023013377175666023563 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`List`.unzip Text Bool [ { _1 = "ABC", _2 = True } , { _1 = "DEF", _2 = False } , { _1 = "GHI", _2 = True } ] dhall-1.19.1/tests/normalization/success/prelude/List/unzip/0B.dhall0000644000000000000000000000007513377175666023573 0ustar0000000000000000{ _1 = [ "ABC", "DEF", "GHI" ], _2 = [ True, False, True ] } dhall-1.19.1/tests/normalization/success/prelude/List/unzip/1A.dhall0000644000000000000000000000014613377175666023572 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`List`.unzip Text Bool ([] : List { _1 : Text, _2 : Bool }) dhall-1.19.1/tests/normalization/success/prelude/List/unzip/1B.dhall0000644000000000000000000000005513377175666023572 0ustar0000000000000000{ _1 = [] : List Text, _2 = [] : List Bool } dhall-1.19.1/tests/normalization/success/prelude/Natural/0000755000000000000000000000000013377175666021650 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Natural/build/0000755000000000000000000000000013377175666022747 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Natural/build/0A.dhall0000644000000000000000000000024713377175666024220 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Natural`.build ( λ(natural : Type) → λ(succ : natural → natural) → λ(zero : natural) → succ (succ (succ zero)) ) dhall-1.19.1/tests/normalization/success/prelude/Natural/build/0B.dhall0000644000000000000000000000000213377175666024206 0ustar00000000000000003 dhall-1.19.1/tests/normalization/success/prelude/Natural/build/1A.dhall0000644000000000000000000000022413377175666024214 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Natural`.build ( λ(natural : Type) → λ(succ : natural → natural) → λ(zero : natural) → zero ) dhall-1.19.1/tests/normalization/success/prelude/Natural/build/1B.dhall0000644000000000000000000000000213377175666024207 0ustar00000000000000000 dhall-1.19.1/tests/normalization/success/prelude/Natural/enumerate/0000755000000000000000000000000013377175666023635 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Natural/enumerate/0A.dhall0000644000000000000000000000010113377175666025073 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Natural`.enumerate 10 dhall-1.19.1/tests/normalization/success/prelude/Natural/enumerate/0B.dhall0000644000000000000000000000004113377175666025077 0ustar0000000000000000[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ] dhall-1.19.1/tests/normalization/success/prelude/Natural/enumerate/1A.dhall0000644000000000000000000000010013377175666025073 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Natural`.enumerate 0 dhall-1.19.1/tests/normalization/success/prelude/Natural/enumerate/1B.dhall0000644000000000000000000000002213377175666025077 0ustar0000000000000000[] : List Natural dhall-1.19.1/tests/normalization/success/prelude/Natural/even/0000755000000000000000000000000013377175666022605 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Natural/even/0A.dhall0000644000000000000000000000007313377175666024053 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Natural`.even 3 dhall-1.19.1/tests/normalization/success/prelude/Natural/even/0B.dhall0000644000000000000000000000000613377175666024050 0ustar0000000000000000False dhall-1.19.1/tests/normalization/success/prelude/Natural/even/1A.dhall0000644000000000000000000000007313377175666024054 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Natural`.even 0 dhall-1.19.1/tests/normalization/success/prelude/Natural/even/1B.dhall0000644000000000000000000000000513377175666024050 0ustar0000000000000000True dhall-1.19.1/tests/normalization/success/prelude/Natural/fold/0000755000000000000000000000000013377175666022574 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Natural/fold/0A.dhall0000644000000000000000000000014113377175666024036 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Natural`.fold 3 Natural (λ(x : Natural) → 5 * x) 1 dhall-1.19.1/tests/normalization/success/prelude/Natural/fold/0B.dhall0000644000000000000000000000000413377175666024035 0ustar0000000000000000125 dhall-1.19.1/tests/normalization/success/prelude/Natural/fold/1A.dhall0000644000000000000000000000017313377175666024044 0ustar0000000000000000λ(zero : Natural) → (../../../../../../Prelude/package.dhall).`Natural`.fold 3 Natural (λ(x : Natural) → 5 * x) zero dhall-1.19.1/tests/normalization/success/prelude/Natural/fold/1B.dhall0000644000000000000000000000005413377175666024043 0ustar0000000000000000λ(zero : Natural) → 5 * (5 * (5 * zero)) dhall-1.19.1/tests/normalization/success/prelude/Natural/fold/2A.dhall0000644000000000000000000000024013377175666024040 0ustar0000000000000000 λ(natural : Type) → λ(succ : natural → natural) → λ(zero : natural) → (../../../../../../Prelude/package.dhall).`Natural`.fold 3 natural succ zero dhall-1.19.1/tests/normalization/success/prelude/Natural/fold/2B.dhall0000644000000000000000000000015113377175666024042 0ustar0000000000000000λ(natural : Type) → λ(succ : natural → natural) → λ(zero : natural) → succ (succ (succ zero)) dhall-1.19.1/tests/normalization/success/prelude/Natural/isZero/0000755000000000000000000000000013377175666023123 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Natural/isZero/0A.dhall0000644000000000000000000000007513377175666024373 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Natural`.isZero 2 dhall-1.19.1/tests/normalization/success/prelude/Natural/isZero/0B.dhall0000644000000000000000000000000613377175666024366 0ustar0000000000000000False dhall-1.19.1/tests/normalization/success/prelude/Natural/isZero/1A.dhall0000644000000000000000000000007513377175666024374 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Natural`.isZero 0 dhall-1.19.1/tests/normalization/success/prelude/Natural/isZero/1B.dhall0000644000000000000000000000000513377175666024366 0ustar0000000000000000True dhall-1.19.1/tests/normalization/success/prelude/Natural/odd/0000755000000000000000000000000013377175666022416 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Natural/odd/0A.dhall0000644000000000000000000000007213377175666023663 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Natural`.odd 3 dhall-1.19.1/tests/normalization/success/prelude/Natural/odd/0B.dhall0000644000000000000000000000000513377175666023660 0ustar0000000000000000True dhall-1.19.1/tests/normalization/success/prelude/Natural/odd/1A.dhall0000644000000000000000000000007213377175666023664 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Natural`.odd 0 dhall-1.19.1/tests/normalization/success/prelude/Natural/odd/1B.dhall0000644000000000000000000000000613377175666023662 0ustar0000000000000000False dhall-1.19.1/tests/normalization/success/prelude/Natural/product/0000755000000000000000000000000013377175666023330 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Natural/product/0A.dhall0000644000000000000000000000011013377175666024566 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Natural`.product [ 2, 3, 5 ] dhall-1.19.1/tests/normalization/success/prelude/Natural/product/0B.dhall0000644000000000000000000000000313377175666024570 0ustar000000000000000030 dhall-1.19.1/tests/normalization/success/prelude/Natural/product/1A.dhall0000644000000000000000000000012013377175666024570 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Natural`.product ([] : List Natural) dhall-1.19.1/tests/normalization/success/prelude/Natural/product/1B.dhall0000644000000000000000000000000213377175666024570 0ustar00000000000000001 dhall-1.19.1/tests/normalization/success/prelude/Natural/show/0000755000000000000000000000000013377175666022630 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Natural/show/0A.dhall0000644000000000000000000000007313377175666024076 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Natural`.show 3 dhall-1.19.1/tests/normalization/success/prelude/Natural/show/0B.dhall0000644000000000000000000000000413377175666024071 0ustar0000000000000000"3" dhall-1.19.1/tests/normalization/success/prelude/Natural/show/1A.dhall0000644000000000000000000000007313377175666024077 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Natural`.show 0 dhall-1.19.1/tests/normalization/success/prelude/Natural/show/1B.dhall0000644000000000000000000000000413377175666024072 0ustar0000000000000000"0" dhall-1.19.1/tests/normalization/success/prelude/Natural/sum/0000755000000000000000000000000013377175666022454 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Natural/sum/0A.dhall0000644000000000000000000000010413377175666023715 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Natural`.sum [ 2, 3, 5 ] dhall-1.19.1/tests/normalization/success/prelude/Natural/sum/0B.dhall0000644000000000000000000000000313377175666023714 0ustar000000000000000010 dhall-1.19.1/tests/normalization/success/prelude/Natural/sum/1A.dhall0000644000000000000000000000011413377175666023717 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Natural`.sum ([] : List Natural) dhall-1.19.1/tests/normalization/success/prelude/Natural/sum/1B.dhall0000644000000000000000000000000213377175666023714 0ustar00000000000000000 dhall-1.19.1/tests/normalization/success/prelude/Natural/toDouble/0000755000000000000000000000000013377175666023425 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Natural/toDouble/0A.dhall0000644000000000000000000000007713377175666024677 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Natural`.toDouble 3 dhall-1.19.1/tests/normalization/success/prelude/Natural/toDouble/0B.dhall0000644000000000000000000000000413377175666024666 0ustar00000000000000003.0 dhall-1.19.1/tests/normalization/success/prelude/Natural/toDouble/1A.dhall0000644000000000000000000000007713377175666024700 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Natural`.toDouble 0 dhall-1.19.1/tests/normalization/success/prelude/Natural/toDouble/1B.dhall0000644000000000000000000000000413377175666024667 0ustar00000000000000000.0 dhall-1.19.1/tests/normalization/success/prelude/Natural/toInteger/0000755000000000000000000000000013377175666023610 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Natural/toInteger/0A.dhall0000644000000000000000000000010013377175666025045 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Natural`.toInteger 3 dhall-1.19.1/tests/normalization/success/prelude/Natural/toInteger/0B.dhall0000644000000000000000000000000313377175666025050 0ustar0000000000000000+3 dhall-1.19.1/tests/normalization/success/prelude/Natural/toInteger/1A.dhall0000644000000000000000000000010013377175666025046 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Natural`.toInteger 0 dhall-1.19.1/tests/normalization/success/prelude/Natural/toInteger/1B.dhall0000644000000000000000000000000313377175666025051 0ustar0000000000000000+0 dhall-1.19.1/tests/normalization/success/prelude/Optional/0000755000000000000000000000000013377175666022027 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Optional/all/0000755000000000000000000000000013377175666022577 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Optional/all/0A.dhall0000644000000000000000000000012713377175666024045 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Optional`.all Natural Natural/even (Some 3) dhall-1.19.1/tests/normalization/success/prelude/Optional/all/0B.dhall0000644000000000000000000000000613377175666024042 0ustar0000000000000000False dhall-1.19.1/tests/normalization/success/prelude/Optional/all/1A.dhall0000644000000000000000000000013513377175666024045 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Optional`.all Natural Natural/even (None Natural) dhall-1.19.1/tests/normalization/success/prelude/Optional/all/1B.dhall0000644000000000000000000000000513377175666024042 0ustar0000000000000000True dhall-1.19.1/tests/normalization/success/prelude/Optional/any/0000755000000000000000000000000013377175666022616 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Optional/any/0A.dhall0000644000000000000000000000012713377175666024064 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Optional`.any Natural Natural/even (Some 2) dhall-1.19.1/tests/normalization/success/prelude/Optional/any/0B.dhall0000644000000000000000000000000513377175666024060 0ustar0000000000000000True dhall-1.19.1/tests/normalization/success/prelude/Optional/any/1A.dhall0000644000000000000000000000013513377175666024064 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Optional`.any Natural Natural/even (None Natural) dhall-1.19.1/tests/normalization/success/prelude/Optional/any/1B.dhall0000644000000000000000000000000613377175666024062 0ustar0000000000000000False dhall-1.19.1/tests/normalization/success/prelude/Optional/build/0000755000000000000000000000000013377175666023126 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Optional/build/0A.dhall0000644000000000000000000000024213377175666024372 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Optional`.build Natural ( λ(optional : Type) → λ(some : Natural → optional) → λ(none : optional) → some 1 ) dhall-1.19.1/tests/normalization/success/prelude/Optional/build/0B.dhall0000644000000000000000000000000713377175666024372 0ustar0000000000000000Some 1 dhall-1.19.1/tests/normalization/success/prelude/Optional/build/1A.dhall0000644000000000000000000000024013377175666024371 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Optional`.build Natural ( λ(optional : Type) → λ(some : Natural → optional) → λ(none : optional) → none ) dhall-1.19.1/tests/normalization/success/prelude/Optional/build/1B.dhall0000644000000000000000000000001513377175666024372 0ustar0000000000000000None Natural dhall-1.19.1/tests/normalization/success/prelude/Optional/concat/0000755000000000000000000000000013377175666023276 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Optional/concat/0A.dhall0000644000000000000000000000012413377175666024541 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Optional`.concat Natural (Some (Some 1)) dhall-1.19.1/tests/normalization/success/prelude/Optional/concat/0B.dhall0000644000000000000000000000000713377175666024542 0ustar0000000000000000Some 1 dhall-1.19.1/tests/normalization/success/prelude/Optional/concat/1A.dhall0000644000000000000000000000013213377175666024541 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Optional`.concat Natural (Some (None Natural)) dhall-1.19.1/tests/normalization/success/prelude/Optional/concat/1B.dhall0000644000000000000000000000001513377175666024542 0ustar0000000000000000None Natural dhall-1.19.1/tests/normalization/success/prelude/Optional/concat/2A.dhall0000644000000000000000000000013613377175666024546 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Optional`.concat Natural (None (Optional Natural)) dhall-1.19.1/tests/normalization/success/prelude/Optional/concat/2B.dhall0000644000000000000000000000001513377175666024543 0ustar0000000000000000None Natural dhall-1.19.1/tests/normalization/success/prelude/Optional/filter/0000755000000000000000000000000013377175666023314 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Optional/filter/0A.dhall0000644000000000000000000000013213377175666024556 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Optional`.filter Natural Natural/even (Some 2) dhall-1.19.1/tests/normalization/success/prelude/Optional/filter/0B.dhall0000644000000000000000000000000713377175666024560 0ustar0000000000000000Some 2 dhall-1.19.1/tests/normalization/success/prelude/Optional/filter/1A.dhall0000644000000000000000000000013113377175666024556 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Optional`.filter Natural Natural/odd (Some 2) dhall-1.19.1/tests/normalization/success/prelude/Optional/filter/1B.dhall0000644000000000000000000000001513377175666024560 0ustar0000000000000000None Natural dhall-1.19.1/tests/normalization/success/prelude/Optional/fold/0000755000000000000000000000000013377175666022753 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Optional/fold/0A.dhall0000644000000000000000000000015513377175666024222 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Optional`.fold Natural (Some 2) Natural (λ(x : Natural) → x) 0 dhall-1.19.1/tests/normalization/success/prelude/Optional/fold/0B.dhall0000644000000000000000000000000213377175666024212 0ustar00000000000000002 dhall-1.19.1/tests/normalization/success/prelude/Optional/fold/1A.dhall0000644000000000000000000000016313377175666024222 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Optional`.fold Natural (None Natural) Natural (λ(x : Natural) → x) 0 dhall-1.19.1/tests/normalization/success/prelude/Optional/fold/1B.dhall0000644000000000000000000000000213377175666024213 0ustar00000000000000000 dhall-1.19.1/tests/normalization/success/prelude/Optional/head/0000755000000000000000000000000013377175666022730 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Optional/head/0A.dhall0000644000000000000000000000014313377175666024174 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Optional`.head Natural [ None Natural, Some 1, Some 2 ] dhall-1.19.1/tests/normalization/success/prelude/Optional/head/0B.dhall0000644000000000000000000000000713377175666024174 0ustar0000000000000000Some 1 dhall-1.19.1/tests/normalization/success/prelude/Optional/head/1A.dhall0000644000000000000000000000014113377175666024173 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Optional`.head Natural [ None Natural, None Natural ] dhall-1.19.1/tests/normalization/success/prelude/Optional/head/1B.dhall0000644000000000000000000000001513377175666024174 0ustar0000000000000000None Natural dhall-1.19.1/tests/normalization/success/prelude/Optional/head/2A.dhall0000644000000000000000000000014113377175666024174 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Optional`.head Natural ([] : List (Optional Natural)) dhall-1.19.1/tests/normalization/success/prelude/Optional/head/2B.dhall0000644000000000000000000000001513377175666024175 0ustar0000000000000000None Natural dhall-1.19.1/tests/normalization/success/prelude/Optional/last/0000755000000000000000000000000013377175666022772 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Optional/last/0A.dhall0000644000000000000000000000014313377175666024236 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Optional`.last Natural [ None Natural, Some 1, Some 2 ] dhall-1.19.1/tests/normalization/success/prelude/Optional/last/0B.dhall0000644000000000000000000000000713377175666024236 0ustar0000000000000000Some 2 dhall-1.19.1/tests/normalization/success/prelude/Optional/last/1A.dhall0000644000000000000000000000014113377175666024235 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Optional`.last Natural [ None Natural, None Natural ] dhall-1.19.1/tests/normalization/success/prelude/Optional/last/1B.dhall0000644000000000000000000000001513377175666024236 0ustar0000000000000000None Natural dhall-1.19.1/tests/normalization/success/prelude/Optional/last/2A.dhall0000644000000000000000000000014113377175666024236 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Optional`.last Natural ([] : List (Optional Natural)) dhall-1.19.1/tests/normalization/success/prelude/Optional/last/2B.dhall0000644000000000000000000000001513377175666024237 0ustar0000000000000000None Natural dhall-1.19.1/tests/normalization/success/prelude/Optional/length/0000755000000000000000000000000013377175666023310 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Optional/length/0A.dhall0000644000000000000000000000011513377175666024553 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Optional`.length Natural (Some 2) dhall-1.19.1/tests/normalization/success/prelude/Optional/length/0B.dhall0000644000000000000000000000000213377175666024547 0ustar00000000000000001 dhall-1.19.1/tests/normalization/success/prelude/Optional/length/1A.dhall0000644000000000000000000000012313377175666024553 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Optional`.length Natural (None Natural) dhall-1.19.1/tests/normalization/success/prelude/Optional/length/1B.dhall0000644000000000000000000000000213377175666024550 0ustar00000000000000000 dhall-1.19.1/tests/normalization/success/prelude/Optional/map/0000755000000000000000000000000013377175666022604 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Optional/map/0A.dhall0000644000000000000000000000013413377175666024050 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Optional`.map Natural Bool Natural/even (Some 3) dhall-1.19.1/tests/normalization/success/prelude/Optional/map/0B.dhall0000644000000000000000000000001313377175666024045 0ustar0000000000000000Some False dhall-1.19.1/tests/normalization/success/prelude/Optional/map/1A.dhall0000644000000000000000000000014213377175666024050 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Optional`.map Natural Bool Natural/even (None Natural) dhall-1.19.1/tests/normalization/success/prelude/Optional/map/1B.dhall0000644000000000000000000000001213377175666024045 0ustar0000000000000000None Bool dhall-1.19.1/tests/normalization/success/prelude/Optional/null/0000755000000000000000000000000013377175666023001 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Optional/null/0A.dhall0000644000000000000000000000011313377175666024242 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Optional`.null Natural (Some 2) dhall-1.19.1/tests/normalization/success/prelude/Optional/null/0B.dhall0000644000000000000000000000000613377175666024244 0ustar0000000000000000False dhall-1.19.1/tests/normalization/success/prelude/Optional/null/1A.dhall0000644000000000000000000000012113377175666024242 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Optional`.null Natural (None Natural) dhall-1.19.1/tests/normalization/success/prelude/Optional/null/1B.dhall0000644000000000000000000000000513377175666024244 0ustar0000000000000000True dhall-1.19.1/tests/normalization/success/prelude/Optional/toList/0000755000000000000000000000000013377175666023305 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Optional/toList/0A.dhall0000644000000000000000000000011513377175666024550 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Optional`.toList Natural (Some 1) dhall-1.19.1/tests/normalization/success/prelude/Optional/toList/0B.dhall0000644000000000000000000000002513377175666024551 0ustar0000000000000000[ 1 ] : List Natural dhall-1.19.1/tests/normalization/success/prelude/Optional/toList/1A.dhall0000644000000000000000000000012313377175666024550 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Optional`.toList Natural (None Natural) dhall-1.19.1/tests/normalization/success/prelude/Optional/toList/1B.dhall0000644000000000000000000000002213377175666024547 0ustar0000000000000000[] : List Natural dhall-1.19.1/tests/normalization/success/prelude/Optional/unzip/0000755000000000000000000000000013377175666023174 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Optional/unzip/0A.dhall0000644000000000000000000000014613377175666024443 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Optional`.unzip Text Bool (Some { _1 = "ABC", _2 = True }) dhall-1.19.1/tests/normalization/success/prelude/Optional/unzip/0B.dhall0000644000000000000000000000004413377175666024441 0ustar0000000000000000{ _1 = Some "ABC", _2 = Some True } dhall-1.19.1/tests/normalization/success/prelude/Optional/unzip/1A.dhall0000644000000000000000000000014513377175666024443 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Optional`.unzip Text Bool (None { _1 : Text, _2 : Bool }) dhall-1.19.1/tests/normalization/success/prelude/Optional/unzip/1B.dhall0000644000000000000000000000004313377175666024441 0ustar0000000000000000{ _1 = None Text, _2 = None Bool } dhall-1.19.1/tests/normalization/success/prelude/Text/0000755000000000000000000000000013377175666021166 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Text/concat/0000755000000000000000000000000013377175666022435 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Text/concat/0A.dhall0000644000000000000000000000012013377175666023674 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Text`.concat [ "ABC", "DEF", "GHI" ] dhall-1.19.1/tests/normalization/success/prelude/Text/concat/0B.dhall0000644000000000000000000000001413377175666023677 0ustar0000000000000000"ABCDEFGHI" dhall-1.19.1/tests/normalization/success/prelude/Text/concat/1A.dhall0000644000000000000000000000011113377175666023675 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Text`.concat ([] : List Text) dhall-1.19.1/tests/normalization/success/prelude/Text/concat/1B.dhall0000644000000000000000000000000313377175666023676 0ustar0000000000000000"" dhall-1.19.1/tests/normalization/success/prelude/Text/concatMap/0000755000000000000000000000000013377175666023073 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Text/concatMap/0A.dhall0000644000000000000000000000017213377175666024341 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Text`.concatMap Natural (λ(n : Natural) → "${Natural/show n} ") [ 0, 1, 2 ] dhall-1.19.1/tests/normalization/success/prelude/Text/concatMap/0B.dhall0000644000000000000000000000001113377175666024332 0ustar0000000000000000"0 1 2 " dhall-1.19.1/tests/normalization/success/prelude/Text/concatMap/1A.dhall0000644000000000000000000000020213377175666024334 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Text`.concatMap Natural (λ(n : Natural) → "${Natural/show n} ") ([] : List Natural) dhall-1.19.1/tests/normalization/success/prelude/Text/concatMap/1B.dhall0000644000000000000000000000000313377175666024334 0ustar0000000000000000"" dhall-1.19.1/tests/normalization/success/prelude/Text/concatMapSep/0000755000000000000000000000000013377175666023543 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Text/concatMapSep/0A.dhall0000644000000000000000000000014413377175666025010 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Text`.concatMapSep ", " Natural Natural/show [ 0, 1, 2 ] dhall-1.19.1/tests/normalization/success/prelude/Text/concatMapSep/0B.dhall0000644000000000000000000000001213377175666025003 0ustar0000000000000000"0, 1, 2" dhall-1.19.1/tests/normalization/success/prelude/Text/concatMapSep/1A.dhall0000644000000000000000000000015413377175666025012 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Text`.concatMapSep ", " Natural Natural/show ([] : List Natural) dhall-1.19.1/tests/normalization/success/prelude/Text/concatMapSep/1B.dhall0000644000000000000000000000000313377175666025004 0ustar0000000000000000"" dhall-1.19.1/tests/normalization/success/prelude/Text/concatSep/0000755000000000000000000000000013377175666023105 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/prelude/Text/concatSep/0A.dhall0000644000000000000000000000013013377175666024345 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Text`.concatSep ", " [ "ABC", "DEF", "GHI" ] dhall-1.19.1/tests/normalization/success/prelude/Text/concatSep/0B.dhall0000644000000000000000000000002013377175666024344 0ustar0000000000000000"ABC, DEF, GHI" dhall-1.19.1/tests/normalization/success/prelude/Text/concatSep/1A.dhall0000644000000000000000000000012113377175666024346 0ustar0000000000000000(../../../../../../Prelude/package.dhall).`Text`.concatSep ", " ([] : List Text) dhall-1.19.1/tests/normalization/success/prelude/Text/concatSep/1B.dhall0000644000000000000000000000000313377175666024346 0ustar0000000000000000"" dhall-1.19.1/tests/normalization/success/simple/0000755000000000000000000000000013377175666020073 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/simple/doubleShowA.dhall0000644000000000000000000000007713377175666023321 0ustar0000000000000000{ example0 = Double/show -0.42, example1 = Double/show 13.37 } dhall-1.19.1/tests/normalization/success/simple/doubleShowB.dhall0000644000000000000000000000005313377175666023314 0ustar0000000000000000{ example0 = "-0.42", example1 = "13.37" } dhall-1.19.1/tests/normalization/success/simple/integerShowA.dhall0000644000000000000000000000013513377175666023477 0ustar0000000000000000{ example0 = Integer/show +1337 , example1 = Integer/show -42 , example2 = Integer/show +0 } dhall-1.19.1/tests/normalization/success/simple/integerShowB.dhall0000644000000000000000000000007213377175666023500 0ustar0000000000000000{ example0 = "+1337", example1 = "-42", example2 = "+0" } dhall-1.19.1/tests/normalization/success/simple/integerToDoubleA.dhall0000644000000000000000000000512313377175666024276 0ustar0000000000000000[ 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-1.19.1/tests/normalization/success/simple/integerToDoubleB.dhall0000644000000000000000000000026213377175666024276 0ustar0000000000000000[ Infinity , 1.7976931348623157e308 , 1.7976931348623157e308 , 1.7976931348623155e308 , -Infinity , -1.7976931348623157e308 , -1.7976931348623157e308 , -1.7976931348623155e308 ] dhall-1.19.1/tests/normalization/success/simple/letletA.dhall0000644000000000000000000000014613377175666022474 0ustar0000000000000000let l = λ(n : Natural) → λ(m : Natural) → λ(x : Natural) → n + m * x let f = l 2 3 in f 445 dhall-1.19.1/tests/normalization/success/simple/letletB.dhall0000644000000000000000000000000513377175666022467 0ustar00000000000000001337 dhall-1.19.1/tests/normalization/success/simple/listBuildA.dhall0000644000000000000000000000103713377175666023136 0ustar0000000000000000{ 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-1.19.1/tests/normalization/success/simple/listBuildB.dhall0000644000000000000000000000026313377175666023137 0ustar0000000000000000{ example0 = [ True, False ] : List Bool , example1 = [ True, False ] : List Bool , example2 = λ(id : ∀(a : Type) → a → a) → id (List Bool) [ True, False ] } dhall-1.19.1/tests/normalization/success/simple/multiLineA.dhall0000644000000000000000000000001713377175666023142 0ustar0000000000000000'' foo bar '' dhall-1.19.1/tests/normalization/success/simple/multiLineB.dhall0000644000000000000000000000001713377175666023143 0ustar0000000000000000'' foo bar '' dhall-1.19.1/tests/normalization/success/simple/naturalBuildA.dhall0000644000000000000000000000072613377175666023635 0ustar0000000000000000{ 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-1.19.1/tests/normalization/success/simple/naturalBuildB.dhall0000644000000000000000000000015513377175666023632 0ustar0000000000000000{ example0 = 1 , example1 = 1 , example2 = λ(id : ∀(a : Type) → a → a) → id Natural 1 } dhall-1.19.1/tests/normalization/success/simple/naturalPlusA.dhall0000644000000000000000000000000613377175666023510 0ustar00000000000000001 + 2 dhall-1.19.1/tests/normalization/success/simple/naturalPlusB.dhall0000644000000000000000000000000213377175666023505 0ustar00000000000000003 dhall-1.19.1/tests/normalization/success/simple/naturalShowA.dhall0000644000000000000000000000002013377175666023501 0ustar0000000000000000Natural/show 42 dhall-1.19.1/tests/normalization/success/simple/naturalShowB.dhall0000644000000000000000000000000513377175666023505 0ustar0000000000000000"42" dhall-1.19.1/tests/normalization/success/simple/naturalToIntegerA.dhall0000644000000000000000000000002413377175666024465 0ustar0000000000000000Natural/toInteger 1 dhall-1.19.1/tests/normalization/success/simple/naturalToIntegerB.dhall0000644000000000000000000000000313377175666024463 0ustar0000000000000000+1 dhall-1.19.1/tests/normalization/success/simple/optionalBuildA.dhall0000644000000000000000000000136413377175666024013 0ustar0000000000000000{ 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-1.19.1/tests/normalization/success/simple/optionalBuildB.dhall0000644000000000000000000000040013377175666024002 0ustar0000000000000000{ example0 = [ 1 ] : Optional Natural , example1 = [ +1 ] : Optional Integer , example2 = λ(id : ∀(a : Type) → a → a) → id (Optional Bool) ([ True ] : Optional Bool) , example3 = λ(a : Type) → λ(x : a) → [ x ] : Optional a } dhall-1.19.1/tests/normalization/success/simple/optionalBuildFoldA.dhall0000644000000000000000000000010513377175666024610 0ustar0000000000000000Optional/build Text (Optional/fold Text ([ "foo" ] : Optional Text)) dhall-1.19.1/tests/normalization/success/simple/optionalBuildFoldB.dhall0000644000000000000000000000003213377175666024610 0ustar0000000000000000[ "foo" ] : Optional Text dhall-1.19.1/tests/normalization/success/simple/optionalFoldA.dhall0000644000000000000000000000031613377175666023634 0ustar0000000000000000 let f = λ(o : Optional Text) → Optional/fold Text o Natural (λ(j : Text) → 1) 2 in { example0 = f ([ "foo" ] : Optional Text) , example1 = f ([] : Optional Text) } dhall-1.19.1/tests/normalization/success/simple/optionalFoldB.dhall0000644000000000000000000000003713377175666023635 0ustar0000000000000000{ example0 = 1, example1 = 2 } dhall-1.19.1/tests/normalization/success/simple/sortOperatorA.dhall0000644000000000000000000000002713377175666023704 0ustar0000000000000000{ b = 2 } // { a = 1 } dhall-1.19.1/tests/normalization/success/simple/sortOperatorB.dhall0000644000000000000000000000002113377175666023677 0ustar0000000000000000{ a = 1, b = 2 } dhall-1.19.1/tests/normalization/success/simplifications/0000755000000000000000000000000013377175666021777 5ustar0000000000000000dhall-1.19.1/tests/normalization/success/simplifications/andA.dhall0000644000000000000000000000031113377175666023643 0ustar0000000000000000{ 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-1.19.1/tests/normalization/success/simplifications/andB.dhall0000644000000000000000000000025213377175666023650 0ustar0000000000000000{ example0 = λ(x : Bool) → x , example1 = λ(x : Bool) → x , example2 = λ(x : Bool) → False , example3 = λ(x : Bool) → False , example4 = λ(x : Bool) → x } dhall-1.19.1/tests/normalization/success/simplifications/eqA.dhall0000644000000000000000000000016713377175666023517 0ustar0000000000000000{ example0 = λ(x : Bool) → x == True , example1 = λ(x : Bool) → True == x , example2 = λ(x : Bool) → x == x } dhall-1.19.1/tests/normalization/success/simplifications/eqB.dhall0000644000000000000000000000014513377175666023514 0ustar0000000000000000{ example0 = λ(x : Bool) → x , example1 = λ(x : Bool) → x , example2 = λ(x : Bool) → True } dhall-1.19.1/tests/normalization/success/simplifications/ifThenElseA.dhall0000644000000000000000000000017413377175666025136 0ustar0000000000000000{ example0 = λ(x : Bool) → if x then True else False , example1 = λ(x : Bool) → λ(y : Text) → if x then y else y } dhall-1.19.1/tests/normalization/success/simplifications/ifThenElseB.dhall0000644000000000000000000000012313377175666025131 0ustar0000000000000000{ example0 = λ(x : Bool) → x , example1 = λ(x : Bool) → λ(y : Text) → y } dhall-1.19.1/tests/normalization/success/simplifications/neA.dhall0000644000000000000000000000017113377175666023507 0ustar0000000000000000{ example0 = λ(x : Bool) → x != False , example1 = λ(x : Bool) → False != x , example2 = λ(x : Bool) → x != x } dhall-1.19.1/tests/normalization/success/simplifications/neB.dhall0000644000000000000000000000014613377175666023512 0ustar0000000000000000{ example0 = λ(x : Bool) → x , example1 = λ(x : Bool) → x , example2 = λ(x : Bool) → False } dhall-1.19.1/tests/normalization/success/simplifications/orA.dhall0000644000000000000000000000031113377175666023521 0ustar0000000000000000{ 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-1.19.1/tests/normalization/success/simplifications/orB.dhall0000644000000000000000000000025013377175666023524 0ustar0000000000000000{ example0 = λ(x : Bool) → True , example1 = λ(x : Bool) → True , example2 = λ(x : Bool) → x , example3 = λ(x : Bool) → x , example4 = λ(x : Bool) → x } dhall-1.19.1/tests/parser/0000755000000000000000000000000013377175666013540 5ustar0000000000000000dhall-1.19.1/tests/parser/failure/0000755000000000000000000000000013377175666015167 5ustar0000000000000000dhall-1.19.1/tests/parser/failure/doubleBoundsNeg.dhall0000644000000000000000000000047113377175666021256 0ustar0000000000000000-179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497792.0 dhall-1.19.1/tests/parser/failure/doubleBoundsPos.dhall0000644000000000000000000000047013377175666021305 0ustar0000000000000000179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497792.0 dhall-1.19.1/tests/parser/failure/importAccess.dhall0000644000000000000000000000002413377175666020625 0ustar0000000000000000./testImport .hello dhall-1.19.1/tests/parser/success/0000755000000000000000000000000013377175666015210 5ustar0000000000000000dhall-1.19.1/tests/parser/success/annotationsA.dhall0000644000000000000000000000031513377175666020653 0ustar0000000000000000{ foo = ([] : List Integer) # [1, 2, 3] # ([1, 2, 3] : List Integer) , bar = [] : Optional Integer , baz = [1] : Optional Integer } : { foo : List Integer, bar : Optional Integer, baz : Optional Integer } dhall-1.19.1/tests/parser/success/annotationsB.dhall0000644000000000000000000000202413377175666020653 0ustar0000000000000000[ 26, [ 8, { "foo": [ 3, 7, [ 3, 7, [ 4, "Integer" ], [ 4, null, [ 15, 1 ], [ 15, 2 ], [ 15, 3 ] ] ], [ 4, null, [ 15, 1 ], [ 15, 2 ], [ 15, 3 ] ] ], "bar": [ 5, "Integer" ], "baz": [ 5, "Integer", [ 15, 1 ] ] } ], [ 7, { "foo": [ 0, "List", "Integer" ], "bar": [ 0, "Optional", "Integer" ], "baz": [ 0, "Optional", "Integer" ] } ] ] dhall-1.19.1/tests/parser/success/blockCommentA.dhall0000644000000000000000000000001513377175666020730 0ustar0000000000000000{- foo -} 1 dhall-1.19.1/tests/parser/success/blockCommentB.dhall0000644000000000000000000000001613377175666020732 0ustar0000000000000000[ 15, 1 ] dhall-1.19.1/tests/parser/success/builtinsA.dhall0000644000000000000000000000135113377175666020150 0ustar0000000000000000 λ ( 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 } dhall-1.19.1/tests/parser/success/builtinsB.dhall0000644000000000000000000000207713377175666020157 0ustar0000000000000000[ 1, "x", [ 7, { "field0": "Bool", "field1": [ 0, "Optional", [ 0, "Optional", "Bool" ] ], "field2": "Natural", "field3": "Integer", "field4": "Double", "field5": "Text", "field6": [ 0, "List", [ 0, "List", "Bool" ] ] } ], [ 8, { "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 } ] ] dhall-1.19.1/tests/parser/success/collectionImportTypeA.dhall0000644000000000000000000000011613377175666022505 0ustar0000000000000000{ example0 = [] : Optional ./type.dhall , example1 = [] : List ./type.dhall } dhall-1.19.1/tests/parser/success/collectionImportTypeB.dhall0000644000000000000000000000031413377175666022506 0ustar0000000000000000[ 8, { "example0": [ 5, [ 24, 3, "type.dhall" ] ], "example1": [ 4, [ 24, 3, "type.dhall" ] ] } ] dhall-1.19.1/tests/parser/success/constructorsA.dhall0000644000000000000000000000005713377175666021071 0ustar0000000000000000constructors < Left : Natural | Right : Bool > dhall-1.19.1/tests/parser/success/constructorsB.dhall0000644000000000000000000000012513377175666021066 0ustar0000000000000000[ 13, [ 11, { "Left": "Natural", "Right": "Bool" } ] ] dhall-1.19.1/tests/parser/success/doubleA.dhall0000644000000000000000000000004013377175666017563 0ustar0000000000000000[ 1.1, -1.1, 1e1, 1.1e1, -1.1 ] dhall-1.19.1/tests/parser/success/doubleB.dhall0000644000000000000000000000022113377175666017565 0ustar0000000000000000[ 4, null, [ 17, 1.1 ], [ 17, -1.1 ], [ 17, 10.0 ], [ 17, 11.0 ], [ 17, -1.1 ] ] dhall-1.19.1/tests/parser/success/doubleQuotedStringA.dhall0000644000000000000000000000000613377175666022136 0ustar0000000000000000"ABC" dhall-1.19.1/tests/parser/success/doubleQuotedStringB.dhall0000644000000000000000000000002213377175666022135 0ustar0000000000000000[ 18, "ABC" ] dhall-1.19.1/tests/parser/success/environmentVariablesA.dhall0000644000000000000000000000010013377175666022503 0ustar0000000000000000[ env:FOO -- Yes, this is legal , env:"\"\\\a\b\f\n\r\t\v" ] dhall-1.19.1/tests/parser/success/environmentVariablesB.dhall0000644000000000000000000000015613377175666022517 0ustar0000000000000000[ 4, null, [ 24, 6, "FOO" ], [ 24, 6, "\\\"\\\\\\a\\b\\f\\n\\r\\t\\v" ] ] dhall-1.19.1/tests/parser/success/escapedDoubleQuotedStringA.dhall0000644000000000000000000000006113377175666023424 0ustar0000000000000000"\\\"\$\\\/\b\f\n\r\t \u2200(a : Type) \u2192 a" dhall-1.19.1/tests/parser/success/escapedDoubleQuotedStringB.dhall0000644000000000000000000000006513377175666023431 0ustar0000000000000000[ 18, "\\\"$\\/\b\f\n\r\t ∀(a : Type) → a" ] dhall-1.19.1/tests/parser/success/escapedSingleQuotedStringA.dhall0000644000000000000000000000001713377175666023434 0ustar0000000000000000'' ''${ ''' '' dhall-1.19.1/tests/parser/success/escapedSingleQuotedStringB.dhall0000644000000000000000000000002713377175666023436 0ustar0000000000000000[ 18, "${\n''\n" ] dhall-1.19.1/tests/parser/success/fieldsA.dhall0000644000000000000000000000006013377175666017561 0ustar0000000000000000({ foo = { bar = { baz = 1 } } }).foo. bar .baz dhall-1.19.1/tests/parser/success/fieldsB.dhall0000644000000000000000000000060213377175666017564 0ustar0000000000000000[ 9, [ 9, [ 9, [ 8, { "foo": [ 8, { "bar": [ 8, { "baz": [ 15, 1 ] } ] } ] } ], "foo" ], "bar" ], "baz" ] dhall-1.19.1/tests/parser/success/forallA.dhall0000644000000000000000000000005113377175666017572 0ustar0000000000000000∀(a : Type) → forall (b : Type) -> a dhall-1.19.1/tests/parser/success/forallB.dhall0000644000000000000000000000010613377175666017574 0ustar0000000000000000[ 2, "a", "Type", [ 2, "b", "Type", "a" ] ] dhall-1.19.1/tests/parser/success/functionTypeA.dhall0000644000000000000000000000002613377175666021004 0ustar0000000000000000Bool → Bool -> Bool dhall-1.19.1/tests/parser/success/functionTypeB.dhall0000644000000000000000000000007113377175666021005 0ustar0000000000000000[ 2, "Bool", [ 2, "Bool", "Bool" ] ] dhall-1.19.1/tests/parser/success/identifierA.dhall0000644000000000000000000000004613377175666020441 0ustar0000000000000000λ(a : Type) → λ(a : Type) → a@1 dhall-1.19.1/tests/parser/success/identifierB.dhall0000644000000000000000000000013513377175666020441 0ustar0000000000000000[ 1, "a", "Type", [ 1, "a", "Type", [ "a", 1 ] ] ] dhall-1.19.1/tests/parser/success/ifThenElseA.dhall0000644000000000000000000000002613377175666020343 0ustar0000000000000000if True then 1 else 2 dhall-1.19.1/tests/parser/success/ifThenElseB.dhall0000644000000000000000000000007713377175666020352 0ustar0000000000000000[ 14, true, [ 15, 1 ], [ 15, 2 ] ] dhall-1.19.1/tests/parser/success/importAltA.dhall0000644000000000000000000000007313377175666020272 0ustar0000000000000000env:UNSET1 as Text ? env:UNSET2 ? missing ? env:UNSET3 ? 2 dhall-1.19.1/tests/parser/success/importAltB.dhall0000644000000000000000000000053613377175666020277 0ustar0000000000000000[ 3, 11, [ 3, 11, [ 3, 11, [ 3, 11, [ 24, 6, "UNSET1" ], [ 24, 6, "UNSET2" ] ], [ 24, 7 ] ], [ 24, 6, "UNSET3" ] ], [ 15, 2 ] ] dhall-1.19.1/tests/parser/success/interpolatedDoubleQuotedStringA.dhall0000644000000000000000000000003113377175666024507 0ustar0000000000000000"ABC${Integer/show 123}" dhall-1.19.1/tests/parser/success/interpolatedDoubleQuotedStringB.dhall0000644000000000000000000000013413377175666024514 0ustar0000000000000000[ 18, "ABC", [ 0, "Integer/show", [ 15, 123 ] ], "" ] dhall-1.19.1/tests/parser/success/interpolatedSingleQuotedStringA.dhall0000644000000000000000000000003613377175666024523 0ustar0000000000000000'' ABC ${Integer/show 123} '' dhall-1.19.1/tests/parser/success/interpolatedSingleQuotedStringB.dhall0000644000000000000000000000014013377175666024520 0ustar0000000000000000[ 18, "ABC\n", [ 0, "Integer/show", [ 15, 123 ] ], "\n" ] dhall-1.19.1/tests/parser/success/labelA.dhall0000644000000000000000000000022013377175666017370 0ustar0000000000000000let _ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-/ = 1 in _ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-/ dhall-1.19.1/tests/parser/success/labelB.dhall0000644000000000000000000000026613377175666017403 0ustar0000000000000000[ 25, "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-/", null, [ 15, 1 ], "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-/" ] dhall-1.19.1/tests/parser/success/lambdaA.dhall0000644000000000000000000000004213377175666017533 0ustar0000000000000000λ(a : Type) → \(b : Type) -> a dhall-1.19.1/tests/parser/success/lambdaB.dhall0000644000000000000000000000010613377175666017535 0ustar0000000000000000[ 1, "a", "Type", [ 1, "b", "Type", "a" ] ] dhall-1.19.1/tests/parser/success/largeExpressionA.dhall0000644000000000000000000002374413377175666021503 0ustar0000000000000000 λ ( 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 ) "" dhall-1.19.1/tests/parser/success/largeExpressionB.dhall0000644000000000000000000016004413377175666021477 0ustar0000000000000000[ 1, "xs", [ 0, "List", [ 7, { "cores": "Natural", "host": "Text", "key": "Text", "mandatoryFeatures": [ 0, "List", "Text" ], "platforms": [ 0, "List", [ 11, { "AArch64_Linux": [ 7, {} ], "ARMv5tel_Linux": [ 7, {} ], "ARMv7l_Linux": [ 7, {} ], "I686_Cygwin": [ 7, {} ], "I686_Linux": [ 7, {} ], "MIPS64el_Linux": [ 7, {} ], "PowerPC_Linux": [ 7, {} ], "X86_64_Cygwin": [ 7, {} ], "X86_64_Darwin": [ 7, {} ], "X86_64_FreeBSD": [ 7, {} ], "X86_64_Linux": [ 7, {} ], "X86_64_Solaris": [ 7, {} ] } ] ], "speedFactor": "Natural", "supportedFeatures": [ 0, "List", "Text" ], "user": [ 0, "Optional", "Text" ] } ] ], [ 0, [ 0, [ 0, [ 0, [ 0, "List/fold", [ 7, { "cores": "Natural", "host": "Text", "key": "Text", "mandatoryFeatures": [ 0, "List", "Text" ], "platforms": [ 0, "List", [ 11, { "AArch64_Linux": [ 7, {} ], "ARMv5tel_Linux": [ 7, {} ], "ARMv7l_Linux": [ 7, {} ], "I686_Cygwin": [ 7, {} ], "I686_Linux": [ 7, {} ], "MIPS64el_Linux": [ 7, {} ], "PowerPC_Linux": [ 7, {} ], "X86_64_Cygwin": [ 7, {} ], "X86_64_Darwin": [ 7, {} ], "X86_64_FreeBSD": [ 7, {} ], "X86_64_Linux": [ 7, {} ], "X86_64_Solaris": [ 7, {} ] } ] ], "speedFactor": "Natural", "supportedFeatures": [ 0, "List", "Text" ], "user": [ 0, "Optional", "Text" ] } ] ], "xs" ], "Text" ], [ 1, "x", [ 7, { "cores": "Natural", "host": "Text", "key": "Text", "mandatoryFeatures": [ 0, "List", "Text" ], "platforms": [ 0, "List", [ 11, { "AArch64_Linux": [ 7, {} ], "ARMv5tel_Linux": [ 7, {} ], "ARMv7l_Linux": [ 7, {} ], "I686_Cygwin": [ 7, {} ], "I686_Linux": [ 7, {} ], "MIPS64el_Linux": [ 7, {} ], "PowerPC_Linux": [ 7, {} ], "X86_64_Cygwin": [ 7, {} ], "X86_64_Darwin": [ 7, {} ], "X86_64_FreeBSD": [ 7, {} ], "X86_64_Linux": [ 7, {} ], "X86_64_Solaris": [ 7, {} ] } ] ], "speedFactor": "Natural", "supportedFeatures": [ 0, "List", "Text" ], "user": [ 0, "Optional", "Text" ] } ], [ 1, "y", "Text", [ 3, 6, [ 3, 6, [ 3, 6, [ 3, 6, [ 3, 6, [ 3, 6, [ 3, 6, [ 3, 6, [ 3, 6, [ 3, 6, [ 3, 6, [ 3, 6, [ 3, 6, [ 3, 6, [ 0, [ 0, [ 0, [ 0, [ 0, "Optional/fold", "Text" ], [ 9, "x", "user" ] ], "Text" ], [ 1, "user", "Text", [ 3, 6, [ 3, 6, [ 3, 6, "user", [ 18, "@" ] ], [ 9, "x", "host" ] ], [ 18, "" ] ] ] ], [ 9, "x", "host" ] ], [ 18, " " ] ], [ 6, [ 8, { "Empty": [ 1, [ 7, {} ], [ 18, "" ] ], "NonEmpty": [ 1, "result", "Text", "result" ] } ], [ 0, [ 0, [ 0, [ 0, [ 0, "List/fold", [ 11, { "AArch64_Linux": [ 7, {} ], "ARMv5tel_Linux": [ 7, {} ], "ARMv7l_Linux": [ 7, {} ], "I686_Cygwin": [ 7, {} ], "I686_Linux": [ 7, {} ], "MIPS64el_Linux": [ 7, {} ], "PowerPC_Linux": [ 7, {} ], "X86_64_Cygwin": [ 7, {} ], "X86_64_Darwin": [ 7, {} ], "X86_64_FreeBSD": [ 7, {} ], "X86_64_Linux": [ 7, {} ], "X86_64_Solaris": [ 7, {} ] } ] ], [ 9, "x", "platforms" ] ], [ 11, { "Empty": [ 7, {} ], "NonEmpty": "Text" } ] ], [ 1, "element", [ 11, { "AArch64_Linux": [ 7, {} ], "ARMv5tel_Linux": [ 7, {} ], "ARMv7l_Linux": [ 7, {} ], "I686_Cygwin": [ 7, {} ], "I686_Linux": [ 7, {} ], "MIPS64el_Linux": [ 7, {} ], "PowerPC_Linux": [ 7, {} ], "X86_64_Cygwin": [ 7, {} ], "X86_64_Darwin": [ 7, {} ], "X86_64_FreeBSD": [ 7, {} ], "X86_64_Linux": [ 7, {} ], "X86_64_Solaris": [ 7, {} ] } ], [ 1, "status", [ 11, { "Empty": [ 7, {} ], "NonEmpty": "Text" } ], [ 6, [ 8, { "Empty": [ 1, [ 7, {} ], [ 12, "NonEmpty", [ 6, [ 8, { "AArch64_Linux": [ 1, [ 7, {} ], [ 18, "aarch64-linux" ] ], "ARMv5tel_Linux": [ 1, [ 7, {} ], [ 18, "armv5tel-linux" ] ], "ARMv7l_Linux": [ 1, [ 7, {} ], [ 18, "armv7l-linux" ] ], "I686_Cygwin": [ 1, [ 7, {} ], [ 18, "i686-cygwin" ] ], "I686_Linux": [ 1, [ 7, {} ], [ 18, "i686-linux" ] ], "MIPS64el_Linux": [ 1, [ 7, {} ], [ 18, "mips64el-linux" ] ], "PowerPC_Linux": [ 1, [ 7, {} ], [ 18, "powerpc-linux" ] ], "X86_64_Cygwin": [ 1, [ 7, {} ], [ 18, "x86_64-cygwin" ] ], "X86_64_Darwin": [ 1, [ 7, {} ], [ 18, "x86_64-darwin" ] ], "X86_64_FreeBSD": [ 1, [ 7, {} ], [ 18, "x86_64-freebsd" ] ], "X86_64_Linux": [ 1, [ 7, {} ], [ 18, "x86_64-linux" ] ], "X86_64_Solaris": [ 1, [ 7, {} ], [ 18, "x86_64-solaris" ] ] } ], "element" ], { "Empty": [ 7, {} ] } ] ], "NonEmpty": [ 1, "result", "Text", [ 12, "NonEmpty", [ 3, 6, [ 3, 6, [ 6, [ 8, { "AArch64_Linux": [ 1, [ 7, {} ], [ 18, "aarch64-linux" ] ], "ARMv5tel_Linux": [ 1, [ 7, {} ], [ 18, "armv5tel-linux" ] ], "ARMv7l_Linux": [ 1, [ 7, {} ], [ 18, "armv7l-linux" ] ], "I686_Cygwin": [ 1, [ 7, {} ], [ 18, "i686-cygwin" ] ], "I686_Linux": [ 1, [ 7, {} ], [ 18, "i686-linux" ] ], "MIPS64el_Linux": [ 1, [ 7, {} ], [ 18, "mips64el-linux" ] ], "PowerPC_Linux": [ 1, [ 7, {} ], [ 18, "powerpc-linux" ] ], "X86_64_Cygwin": [ 1, [ 7, {} ], [ 18, "x86_64-cygwin" ] ], "X86_64_Darwin": [ 1, [ 7, {} ], [ 18, "x86_64-darwin" ] ], "X86_64_FreeBSD": [ 1, [ 7, {} ], [ 18, "x86_64-freebsd" ] ], "X86_64_Linux": [ 1, [ 7, {} ], [ 18, "x86_64-linux" ] ], "X86_64_Solaris": [ 1, [ 7, {} ], [ 18, "x86_64-solaris" ] ] } ], "element" ], [ 18, "," ] ], "result" ], { "Empty": [ 7, {} ] } ] ] } ], "status", [ 11, { "Empty": [ 7, {} ], "NonEmpty": "Text" } ] ] ] ] ], [ 12, "Empty", [ 8, {} ], { "NonEmpty": "Text" } ] ], "Text" ] ], [ 18, " " ] ], [ 9, "x", "key" ] ], [ 18, " " ] ], [ 0, "Integer/show", [ 0, "Natural/toInteger", [ 9, "x", "cores" ] ] ] ], [ 18, " " ] ], [ 0, "Integer/show", [ 0, "Natural/toInteger", [ 9, "x", "speedFactor" ] ] ] ], [ 18, " " ] ], [ 6, [ 8, { "Empty": [ 1, [ 7, {} ], [ 18, "" ] ], "NonEmpty": [ 1, "result", "Text", "result" ] } ], [ 0, [ 0, [ 0, [ 0, [ 0, "List/fold", "Text" ], [ 9, "x", "supportedFeatures" ] ], [ 11, { "Empty": [ 7, {} ], "NonEmpty": "Text" } ] ], [ 1, "element", "Text", [ 1, "status", [ 11, { "Empty": [ 7, {} ], "NonEmpty": "Text" } ], [ 6, [ 8, { "Empty": [ 1, [ 7, {} ], [ 12, "NonEmpty", "element", { "Empty": [ 7, {} ] } ] ], "NonEmpty": [ 1, "result", "Text", [ 12, "NonEmpty", [ 3, 6, [ 3, 6, "element", [ 18, "," ] ], "result" ], { "Empty": [ 7, {} ] } ] ] } ], "status", [ 11, { "Empty": [ 7, {} ], "NonEmpty": "Text" } ] ] ] ] ], [ 12, "Empty", [ 8, {} ], { "NonEmpty": "Text" } ] ], "Text" ] ], [ 18, " " ] ], [ 6, [ 8, { "Empty": [ 1, [ 7, {} ], [ 18, "" ] ], "NonEmpty": [ 1, "result", "Text", "result" ] } ], [ 0, [ 0, [ 0, [ 0, [ 0, "List/fold", "Text" ], [ 9, "x", "mandatoryFeatures" ] ], [ 11, { "Empty": [ 7, {} ], "NonEmpty": "Text" } ] ], [ 1, "element", "Text", [ 1, "status", [ 11, { "Empty": [ 7, {} ], "NonEmpty": "Text" } ], [ 6, [ 8, { "Empty": [ 1, [ 7, {} ], [ 12, "NonEmpty", "element", { "Empty": [ 7, {} ] } ] ], "NonEmpty": [ 1, "result", "Text", [ 12, "NonEmpty", [ 3, 6, [ 3, 6, "element", [ 18, "," ] ], "result" ], { "Empty": [ 7, {} ] } ] ] } ], "status", [ 11, { "Empty": [ 7, {} ], "NonEmpty": "Text" } ] ] ] ] ], [ 12, "Empty", [ 8, {} ], { "NonEmpty": "Text" } ] ], "Text" ] ], [ 18, "\n" ] ], "y" ] ] ] ], [ 18, "" ] ] ] dhall-1.19.1/tests/parser/success/letA.dhall0000644000000000000000000000005413377175666017102 0ustar0000000000000000 let x = 1 in let y : Integer = 2 in x dhall-1.19.1/tests/parser/success/letB.dhall0000644000000000000000000000017713377175666017111 0ustar0000000000000000[ 25, "x", null, [ 15, 1 ], [ 25, "y", "Integer", [ 15, 2 ], "x" ] ] dhall-1.19.1/tests/parser/success/lineCommentA.dhall0000644000000000000000000000001213377175666020562 0ustar0000000000000000-- foo 1 dhall-1.19.1/tests/parser/success/lineCommentB.dhall0000644000000000000000000000001613377175666020567 0ustar0000000000000000[ 15, 1 ] dhall-1.19.1/tests/parser/success/listA.dhall0000644000000000000000000000007513377175666017274 0ustar0000000000000000[ [1, 2, 3] , [1, 2, 3] : List Integer , [] : List Integer ] dhall-1.19.1/tests/parser/success/listB.dhall0000644000000000000000000000043213377175666017272 0ustar0000000000000000[ 4, null, [ 4, null, [ 15, 1 ], [ 15, 2 ], [ 15, 3 ] ], [ 4, null, [ 15, 1 ], [ 15, 2 ], [ 15, 3 ] ], [ 4, "Integer" ] ] dhall-1.19.1/tests/parser/success/mergeA.dhall0000644000000000000000000000025313377175666017416 0ustar0000000000000000 λ(x : <>) → { bar = merge {=} x : Integer , foo = merge { Left = λ(b : Bool) → b, Right = Natural/even } < Left = True | Right : Natural > } dhall-1.19.1/tests/parser/success/mergeB.dhall0000644000000000000000000000104013377175666017412 0ustar0000000000000000[ 1, "x", [ 11, {} ], [ 8, { "bar": [ 6, [ 8, {} ], "x", "Integer" ], "foo": [ 6, [ 8, { "Left": [ 1, "b", "Bool", "b" ], "Right": "Natural/even" } ], [ 12, "Left", true, { "Right": "Natural" } ] ] } ] ] dhall-1.19.1/tests/parser/success/multiletA.dhall0000644000000000000000000000003613377175666020155 0ustar0000000000000000let a = 1 let b = 2 in a + b dhall-1.19.1/tests/parser/success/multiletB.dhall0000644000000000000000000000017513377175666020162 0ustar0000000000000000[ 25, "a", null, [ 15, 1 ], "b", null, [ 15, 2 ], [ 3, 4, "a", "b" ] ] dhall-1.19.1/tests/parser/success/naturalA.dhall0000644000000000000000000000002513377175666017762 0ustar0000000000000000[ +0, +1, +01, +10 ] dhall-1.19.1/tests/parser/success/naturalB.dhall0000644000000000000000000000015513377175666017767 0ustar0000000000000000[ 4, null, [ 16, 0 ], [ 16, 1 ], [ 16, 1 ], [ 16, 10 ] ] dhall-1.19.1/tests/parser/success/nestedBlockCommentA.dhall0000644000000000000000000000003313377175666022073 0ustar0000000000000000{- foo {- bar -} baz -} 1 dhall-1.19.1/tests/parser/success/nestedBlockCommentB.dhall0000644000000000000000000000001613377175666022075 0ustar0000000000000000[ 15, 1 ] dhall-1.19.1/tests/parser/success/operatorsA.dhall0000644000000000000000000000021413377175666020332 0ustar0000000000000000 { foo = (False && Natural/even (+1 + +2 * +3)) || True == False != True } ∧ { bar = [ "ABC" ++ "DEF" ] # [ "GHI" ] } ⫽ { baz = True } dhall-1.19.1/tests/parser/success/operatorsB.dhall0000644000000000000000000000241413377175666020337 0ustar0000000000000000[ 3, 8, [ 8, { "foo": [ 3, 0, [ 3, 1, false, [ 0, "Natural/even", [ 3, 4, [ 16, 1 ], [ 3, 5, [ 16, 2 ], [ 16, 3 ] ] ] ] ], [ 3, 3, [ 3, 2, true, false ], true ] ] } ], [ 3, 9, [ 8, { "bar": [ 3, 7, [ 4, null, [ 3, 6, [ 18, "ABC" ], [ 18, "DEF" ] ] ], [ 4, null, [ 18, "GHI" ] ] ] } ], [ 8, { "baz": true } ] ] ] dhall-1.19.1/tests/parser/success/parenthesizeUsingA.dhall0000644000000000000000000000041713377175666022030 0ustar0000000000000000https://raw.githubusercontent.com/dhall-lang/Prelude/c79c2bc3c46f129cc5b6d594ce298a381bcae92c/List/replicate using (./a.dhall sha256:16173e984d35ee3ffd8b6b79167df89480e67d1cd03ea5d0fc93689e4d928e61) sha256:b0e3ec1797b32c80c0bcb7e8254b08c7e9e35e75e6b410c7ac21477ab90167ad dhall-1.19.1/tests/parser/success/parenthesizeUsingB.dhall0000644000000000000000000000024113377175666022024 0ustar0000000000000000[ 24, 1, "raw.githubusercontent.com", "dhall-lang", "Prelude", "c79c2bc3c46f129cc5b6d594ce298a381bcae92c", "List", "replicate", null, null ] dhall-1.19.1/tests/parser/success/pathsA.dhall0000644000000000000000000000017313377175666017437 0ustar0000000000000000[ /absolute/path , ./relative/path , ~/home/anchored/path , /ipfs/QmQ8w5PLcsNz56dMvRtq54vbuPe9cNnCCUXAQp6xLc6Ccx/Prelude ] dhall-1.19.1/tests/parser/success/pathsB.dhall0000644000000000000000000000043513377175666017441 0ustar0000000000000000[ 4, null, [ 24, 2, "absolute", "path" ], [ 24, 3, "relative", "path" ], [ 24, 5, "home", "anchored", "path" ], [ 24, 2, "ipfs", "QmQ8w5PLcsNz56dMvRtq54vbuPe9cNnCCUXAQp6xLc6Ccx", "Prelude" ] ] dhall-1.19.1/tests/parser/success/pathTerminationA.dhall0000644000000000000000000000027113377175666021465 0ustar0000000000000000-- Verify that certain punctuation marks terminate paths correctly λ(x : ./example) → ./example[./example, ./example{bar = ./example, qux = ./example}, ./example] dhall-1.19.1/tests/parser/success/pathTerminationB.dhall0000644000000000000000000000154113377175666021467 0ustar0000000000000000[ 1, "x", [ 24, 3, "example" ], [ 0, [ 24, 3, "example" ], [ 4, null, [ 24, 3, "example" ], [ 0, [ 24, 3, "example" ], [ 8, { "bar": [ 0, [ 24, 3, "example" ], [ 12, "baz", [ 24, 3, "example" ], {} ] ], "qux": [ 24, 3, "example" ] } ] ], [ 24, 3, "example" ] ] ] ] dhall-1.19.1/tests/parser/success/quotedLabelA.dhall0000644000000000000000000000015613377175666020562 0ustar0000000000000000{ example1 = let `let` = 1 in `let` , example2 = let `:.` = 1 in `:.` , example3 = let `$ref` = 1 in `$ref` } dhall-1.19.1/tests/parser/success/quotedLabelB.dhall0000644000000000000000000000053513377175666020564 0ustar0000000000000000[ 8, { "example1": [ 25, "let", null, [ 15, 1 ], "let" ], "example2": [ 25, ":.", null, [ 15, 1 ], ":." ], "example3": [ 25, "$ref", null, [ 15, 1 ], "$ref" ] } ] dhall-1.19.1/tests/parser/success/quotedPathsA.dhall0000644000000000000000000000012713377175666020620 0ustar0000000000000000{ example0 = /"foo"/bar/"baz qux" , example1 = https://example.com/foo/"bar?baz"?qux } dhall-1.19.1/tests/parser/success/quotedPathsB.dhall0000644000000000000000000000033513377175666020622 0ustar0000000000000000[ 8, { "example0": [ 24, 2, "foo", "bar", "baz qux" ], "example1": [ 24, 1, "example.com", "foo", "bar?baz", "qux", null ] } ] dhall-1.19.1/tests/parser/success/recordA.dhall0000644000000000000000000000012313377175666017571 0ustar0000000000000000{ foo = 1 , bar = +2 , baz = True } : { foo : Integer, bar : Natural, baz : Bool } dhall-1.19.1/tests/parser/success/recordB.dhall0000644000000000000000000000036313377175666017600 0ustar0000000000000000[ 26, [ 8, { "foo": [ 15, 1 ], "bar": [ 16, 2 ], "baz": true } ], [ 7, { "foo": "Integer", "bar": "Natural", "baz": "Bool" } ] ] dhall-1.19.1/tests/parser/success/reservedPrefixA.dhall0000644000000000000000000000005513377175666021314 0ustar0000000000000000let TypeSynonym = Integer in 1 : TypeSynonym dhall-1.19.1/tests/parser/success/reservedPrefixB.dhall0000644000000000000000000000016113377175666021313 0ustar0000000000000000[ 25, "TypeSynonym", null, "Integer", [ 26, [ 15, 1 ], "TypeSynonym" ] ] dhall-1.19.1/tests/parser/success/singleQuotedStringA.dhall0000644000000000000000000000001613377175666022146 0ustar0000000000000000'' ABC DEF '' dhall-1.19.1/tests/parser/success/singleQuotedStringB.dhall0000644000000000000000000000003113377175666022144 0ustar0000000000000000[ 18, "ABC\nDEF\n" ] dhall-1.19.1/tests/parser/success/sortA.dhall0000644000000000000000000000000513377175666017301 0ustar0000000000000000Sort dhall-1.19.1/tests/parser/success/sortB.dhall0000644000000000000000000000000713377175666017304 0ustar0000000000000000"Sort" dhall-1.19.1/tests/parser/success/templateA.dhall0000644000000000000000000000055213377175666020134 0ustar0000000000000000 \(record : { name : Text , value : Double , taxed_value : Double , in_ca : Bool } ) -> '' Hello ${record.name} You have just won ${Double/show record.value} dollars! ${ if record.in_ca then "Well, ${Double/show record.taxed_value} dollars, after taxes" else "" } '' dhall-1.19.1/tests/parser/success/templateB.dhall0000644000000000000000000000134313377175666020134 0ustar0000000000000000[ 1, "record", [ 7, { "name": "Text", "value": "Double", "taxed_value": "Double", "in_ca": "Bool" } ], [ 18, "Hello ", [ 9, "record", "name" ], "\nYou have just won ", [ 0, "Double/show", [ 9, "record", "value" ] ], " dollars!\n", [ 14, [ 9, "record", "in_ca" ], [ 18, "Well, ", [ 0, "Double/show", [ 9, "record", "taxed_value" ] ], " dollars, after taxes" ], [ 18, "" ] ], "\n" ] ] dhall-1.19.1/tests/parser/success/unicodeCommentA.dhall0000644000000000000000000000003513377175666021266 0ustar0000000000000000{- ∀(a : Type) → a -} 1 dhall-1.19.1/tests/parser/success/unicodeCommentB.dhall0000644000000000000000000000001613377175666021266 0ustar0000000000000000[ 15, 1 ] dhall-1.19.1/tests/parser/success/unicodeDoubleQuotedStringA.dhall0000644000000000000000000000002613377175666023447 0ustar0000000000000000"∀(a : Type) → a" dhall-1.19.1/tests/parser/success/unicodeDoubleQuotedStringB.dhall0000644000000000000000000000004213377175666023446 0ustar0000000000000000[ 18, "∀(a : Type) → a" ] dhall-1.19.1/tests/parser/success/unionA.dhall0000644000000000000000000000010213377175666017440 0ustar0000000000000000< A : { } | B = { = } | C : {} > : < A : {} | B : {} | C : {} > dhall-1.19.1/tests/parser/success/unionB.dhall0000644000000000000000000000050513377175666017450 0ustar0000000000000000[ 26, [ 12, "B", [ 8, {} ], { "A": [ 7, {} ], "C": [ 7, {} ] } ], [ 11, { "A": [ 7, {} ], "B": [ 7, {} ], "C": [ 7, {} ] } ] ] dhall-1.19.1/tests/parser/success/urlsA.dhall0000644000000000000000000000111313377175666017300 0ustar0000000000000000[ http://example.com/someFile.dhall , https://john:doe@example.com:8080/foo/bar?qux=0#xyzzy , http://prelude.dhall-lang.org/package.dhall , https://ipfs.io/ipfs/QmQ8w5PLcsNz56dMvRtq54vbuPe9cNnCCUXAQp6xLc6Ccx/Prelude , https://raw.githubusercontent.com/dhall-lang/dhall-haskell/18e4e9a18dc53271146df3ccf5b4177c3552236b/examples/True , https://127.0.0.1/index.dhall , https://[::]/index.dhall , https://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]/tutorial.dhall -- Yes, this is legal , https://-._~%2C!$&'()*+,;=:@-._~%2C!$&'()*+,;=:/foo?/-._~%2C!$&'()*+,;=:@/?#/-._~%2C!$&'()*+,;=:@/? ] dhall-1.19.1/tests/parser/success/urlsB.dhall0000644000000000000000000000201613377175666017304 0ustar0000000000000000[ 4, null, [ 24, 0, "example.com", "someFile.dhall", null, null ], [ 24, 1, "john:doe@example.com:8080", "foo", "bar", "qux=0", "xyzzy" ], [ 24, 0, "prelude.dhall-lang.org", "package.dhall", null, null ], [ 24, 1, "ipfs.io", "ipfs", "QmQ8w5PLcsNz56dMvRtq54vbuPe9cNnCCUXAQp6xLc6Ccx", "Prelude", null, null ], [ 24, 1, "raw.githubusercontent.com", "dhall-lang", "dhall-haskell", "18e4e9a18dc53271146df3ccf5b4177c3552236b", "examples", "True", null, null ], [ 24, 1, "127.0.0.1", "index.dhall", null, null ], [ 24, 1, "[::]", "index.dhall", null, null ], [ 24, 1, "[2001:0db8:85a3:0000:0000:8a2e:0370:7334]", "tutorial.dhall", null, null ], [ 24, 1, "-._~%2C!$&'()*+,;=:@-._~%2C!$&'()*+,;=:", "foo", "/-._~%2C!$&'()*+,;=:@/?", "/-._~%2C!$&'()*+,;=:@/?" ] ] dhall-1.19.1/tests/parser/success/whitespaceA.dhall0000644000000000000000000000000413377175666020445 0ustar0000000000000000 1 dhall-1.19.1/tests/parser/success/whitespaceB.dhall0000644000000000000000000000001613377175666020451 0ustar0000000000000000[ 15, 1 ] dhall-1.19.1/tests/parser/success/whitespaceBuffetA.dhall0000644000000000000000000000013513377175666021606 0ustar0000000000000000 -- This Natural/even {- {- file -} has -} +2 -- mixed {- line endings -} dhall-1.19.1/tests/parser/success/whitespaceBuffetB.dhall0000644000000000000000000000006113377175666021605 0ustar0000000000000000[ 0, "Natural/even", [ 16, 2 ] ] dhall-1.19.1/tests/regression/0000755000000000000000000000000013377175666014424 5ustar0000000000000000dhall-1.19.1/tests/regression/issue151a.dhall0000644000000000000000000000007113377175666017150 0ustar0000000000000000let foo : (\(x : A) -> x x) (\(x : A) -> x x) = 1 in foo dhall-1.19.1/tests/regression/issue151b.dhall0000644000000000000000000000007413377175666017154 0ustar0000000000000000\(omega : ((\(x : A) -> x x) (\(x : A) -> x x))) -> omega 1 dhall-1.19.1/tests/regression/issue164.dhall0000644000000000000000000000010513377175666017011 0ustar0000000000000000''Single quotes like ' should be allowed in a single-quoted string'' dhall-1.19.1/tests/regression/issue201.dhall0000644000000000000000000000003213377175666017000 0ustar0000000000000000let Foo = {} in {=} : Foo dhall-1.19.1/tests/regression/issue209.dhall0000644000000000000000000000002013377175666017005 0ustar0000000000000000constructors <> dhall-1.19.1/tests/regression/issue216a.dhall0000644000000000000000000000037013377175666017154 0ustar0000000000000000let GitHubProject : Type = { owner : Text, repo : Text } in let gitHubProject = \( github : GitHubProject ) -> let gitHubRoot = "https://github.com/${github.owner}/${github.repo}" in { bugReports = "${gitHubRoot}/issues" } in gitHubProject dhall-1.19.1/tests/regression/issue216b.dhall0000644000000000000000000000017413377175666017157 0ustar0000000000000000 λ(github : { owner : Text, repo : Text }) → { bugReports = "https://github.com/${github.owner}/${github.repo}/issues" }dhall-1.19.1/tests/tutorial/0000755000000000000000000000000013377175666014107 5ustar0000000000000000dhall-1.19.1/tests/tutorial/process.dhall0000644000000000000000000000035113377175666016572 0ustar0000000000000000 λ(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 dhall-1.19.1/tests/tutorial/unions0A.dhall0000644000000000000000000000005413377175666016610 0ustar0000000000000000./process.dhall < Left = 3 | Right : Bool > dhall-1.19.1/tests/tutorial/unions0B.dhall0000644000000000000000000000000613377175666016606 0ustar0000000000000000False dhall-1.19.1/tests/tutorial/unions1A.dhall0000644000000000000000000000006213377175666016610 0ustar0000000000000000./process.dhall < Right = True | Left : Natural > dhall-1.19.1/tests/tutorial/unions1B.dhall0000644000000000000000000000000513377175666016606 0ustar0000000000000000True dhall-1.19.1/tests/tutorial/unions2A.dhall0000644000000000000000000000044313377175666016614 0ustar0000000000000000 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 ] dhall-1.19.1/tests/tutorial/unions2B.dhall0000644000000000000000000000035113377175666016613 0ustar0000000000000000[ < Empty = {=} | Person : { age : Natural, name : Text } > , < Person = { age = 23, name = "John" } | Empty : {} > , < Person = { age = 25, name = "Amy" } | Empty : {} > , < Empty = {=} | Person : { age : Natural, name : Text } > ] dhall-1.19.1/tests/tutorial/unions3A.dhall0000644000000000000000000000033213377175666016612 0ustar0000000000000000 let MyType = constructors < Empty : {} | Person : { name : Text, age : Natural } > in [ MyType.Empty {=} , MyType.Person { name = "John", age = 23 } , MyType.Person { name = "Amy" , age = 25 } ] dhall-1.19.1/tests/tutorial/unions3B.dhall0000644000000000000000000000025513377175666016617 0ustar0000000000000000[ < Empty = {=} | Person : { age : Natural, name : Text } > , < Person = { age = 23, name = "John" } | Empty : {} > , < Person = { age = 25, name = "Amy" } | Empty : {} > ] dhall-1.19.1/tests/tutorial/unions4A.dhall0000644000000000000000000000010613377175666016612 0ustar0000000000000000constructors < Empty : {} | Person : { name : Text, age : Natural } > dhall-1.19.1/tests/tutorial/unions4B.dhall0000644000000000000000000000030613377175666016615 0ustar0000000000000000{ Empty = λ(Empty : {}) → < Empty = Empty | Person : { age : Natural, name : Text } > , Person = λ(Person : { age : Natural, name : Text }) → < Person = Person | Empty : {} > } dhall-1.19.1/tests/typecheck/0000755000000000000000000000000013377175666014223 5ustar0000000000000000dhall-1.19.1/tests/typecheck/failure/0000755000000000000000000000000013377175666015652 5ustar0000000000000000dhall-1.19.1/tests/typecheck/failure/combineMixedRecords.dhall0000644000000000000000000000003713377175666022605 0ustar0000000000000000{ foo = 1 } ∧ { bar = Text } dhall-1.19.1/tests/typecheck/failure/hurkensParadox.dhall0000644000000000000000000000300213377175666021651 0ustar0000000000000000 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-1.19.1/tests/typecheck/failure/preferMixedRecords.dhall0000644000000000000000000000003713377175666022454 0ustar0000000000000000{ foo = 1 } ⫽ { bar = Text } dhall-1.19.1/tests/typecheck/success/0000755000000000000000000000000013377175666015673 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/accessEncodedTypeA.dhall0000644000000000000000000000026213377175666022367 0ustar0000000000000000 λ ( record : ∀(k : Kind) → ∀(makeRecord : ∀(x : Type) → ∀(y : Type → Type) → k) → k ) → record Type (λ(x : Type) → λ(y : Type → Type) → x) dhall-1.19.1/tests/typecheck/success/accessEncodedTypeB.dhall0000644000000000000000000000017513377175666022373 0ustar0000000000000000 ∀ ( record : ∀(k : Kind) → ∀(makeRecord : ∀(x : Type) → ∀(y : Type → Type) → k) → k ) → Type dhall-1.19.1/tests/typecheck/success/accessTypeA.dhall0000644000000000000000000000007213377175666021104 0ustar0000000000000000λ(record : { x : Type, y : Type → Type }) → record.x dhall-1.19.1/tests/typecheck/success/accessTypeB.dhall0000644000000000000000000000006713377175666021111 0ustar0000000000000000∀(record : { x : Type, y : Type → Type }) → Type dhall-1.19.1/tests/typecheck/success/encodedRecordOfTypesA.dhall0000644000000000000000000000015413377175666023054 0ustar0000000000000000 λ(k : Kind) → λ(makeRecord : ∀(x : Type) → ∀(y : Type → Type) → k) → makeRecord Text List dhall-1.19.1/tests/typecheck/success/encodedRecordOfTypesB.dhall0000644000000000000000000000013113377175666023050 0ustar0000000000000000∀(k : Kind) → ∀(makeRecord : ∀(x : Type) → ∀(y : Type → Type) → k) → k dhall-1.19.1/tests/typecheck/success/recordOfTypesA.dhall0000644000000000000000000000002713377175666021571 0ustar0000000000000000{ x = Text, y = List } dhall-1.19.1/tests/typecheck/success/recordOfTypesB.dhall0000644000000000000000000000004013377175666021565 0ustar0000000000000000{ x : Type, y : Type → Type } dhall-1.19.1/tests/typecheck/success/prelude/0000755000000000000000000000000013377175666017333 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Bool/0000755000000000000000000000000013377175666020226 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Bool/and/0000755000000000000000000000000013377175666020770 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Bool/and/0A.dhall0000644000000000000000000000007113377175666022234 0ustar0000000000000000../../../../../../Prelude/Bool/and [ True, False, True ] dhall-1.19.1/tests/typecheck/success/prelude/Bool/and/0B.dhall0000644000000000000000000000000513377175666022232 0ustar0000000000000000Bool dhall-1.19.1/tests/typecheck/success/prelude/Bool/and/1A.dhall0000644000000000000000000000006413377175666022237 0ustar0000000000000000../../../../../../Prelude/Bool/and ([] : List Bool) dhall-1.19.1/tests/typecheck/success/prelude/Bool/and/1B.dhall0000644000000000000000000000000513377175666022233 0ustar0000000000000000Bool dhall-1.19.1/tests/typecheck/success/prelude/Bool/build/0000755000000000000000000000000013377175666021325 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Bool/build/0A.dhall0000644000000000000000000000015213377175666022571 0ustar0000000000000000../../../../../../Prelude/Bool/build (λ(bool : Type) → λ(true : bool) → λ(false : bool) → true) dhall-1.19.1/tests/typecheck/success/prelude/Bool/build/0B.dhall0000644000000000000000000000000513377175666022567 0ustar0000000000000000Bool dhall-1.19.1/tests/typecheck/success/prelude/Bool/build/1A.dhall0000644000000000000000000000015313377175666022573 0ustar0000000000000000../../../../../../Prelude/Bool/build (λ(bool : Type) → λ(true : bool) → λ(false : bool) → false) dhall-1.19.1/tests/typecheck/success/prelude/Bool/build/1B.dhall0000644000000000000000000000000513377175666022570 0ustar0000000000000000Bool dhall-1.19.1/tests/typecheck/success/prelude/Bool/even/0000755000000000000000000000000013377175666021163 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Bool/even/0A.dhall0000644000000000000000000000007313377175666022431 0ustar0000000000000000../../../../../../Prelude/Bool/even [ False, True, False ] dhall-1.19.1/tests/typecheck/success/prelude/Bool/even/0B.dhall0000644000000000000000000000000513377175666022425 0ustar0000000000000000Bool dhall-1.19.1/tests/typecheck/success/prelude/Bool/even/1A.dhall0000644000000000000000000000006413377175666022432 0ustar0000000000000000../../../../../../Prelude/Bool/even [ False, True ] dhall-1.19.1/tests/typecheck/success/prelude/Bool/even/1B.dhall0000644000000000000000000000000513377175666022426 0ustar0000000000000000Bool dhall-1.19.1/tests/typecheck/success/prelude/Bool/even/2A.dhall0000644000000000000000000000005613377175666022434 0ustar0000000000000000../../../../../../Prelude/Bool/even [ False ] dhall-1.19.1/tests/typecheck/success/prelude/Bool/even/2B.dhall0000644000000000000000000000000513377175666022427 0ustar0000000000000000Bool dhall-1.19.1/tests/typecheck/success/prelude/Bool/even/3A.dhall0000644000000000000000000000006513377175666022435 0ustar0000000000000000../../../../../../Prelude/Bool/even ([] : List Bool) dhall-1.19.1/tests/typecheck/success/prelude/Bool/even/3B.dhall0000644000000000000000000000000513377175666022430 0ustar0000000000000000Bool dhall-1.19.1/tests/typecheck/success/prelude/Bool/fold/0000755000000000000000000000000013377175666021152 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Bool/fold/0A.dhall0000644000000000000000000000006513377175666022421 0ustar0000000000000000../../../../../../Prelude/Bool/fold True Natural 0 1 dhall-1.19.1/tests/typecheck/success/prelude/Bool/fold/0B.dhall0000644000000000000000000000001013377175666022410 0ustar0000000000000000Natural dhall-1.19.1/tests/typecheck/success/prelude/Bool/fold/1A.dhall0000644000000000000000000000006613377175666022423 0ustar0000000000000000../../../../../../Prelude/Bool/fold False Natural 0 1 dhall-1.19.1/tests/typecheck/success/prelude/Bool/fold/1B.dhall0000644000000000000000000000001013377175666022411 0ustar0000000000000000Natural dhall-1.19.1/tests/typecheck/success/prelude/Bool/not/0000755000000000000000000000000013377175666021026 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Bool/not/0A.dhall0000644000000000000000000000005013377175666022267 0ustar0000000000000000../../../../../../Prelude/Bool/not True dhall-1.19.1/tests/typecheck/success/prelude/Bool/not/0B.dhall0000644000000000000000000000000513377175666022270 0ustar0000000000000000Bool dhall-1.19.1/tests/typecheck/success/prelude/Bool/not/1A.dhall0000644000000000000000000000005113377175666022271 0ustar0000000000000000../../../../../../Prelude/Bool/not False dhall-1.19.1/tests/typecheck/success/prelude/Bool/not/1B.dhall0000644000000000000000000000000513377175666022271 0ustar0000000000000000Bool dhall-1.19.1/tests/typecheck/success/prelude/Bool/odd/0000755000000000000000000000000013377175666020774 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Bool/odd/0A.dhall0000644000000000000000000000007113377175666022240 0ustar0000000000000000../../../../../../Prelude/Bool/odd [ True, False, True ] dhall-1.19.1/tests/typecheck/success/prelude/Bool/odd/0B.dhall0000644000000000000000000000000513377175666022236 0ustar0000000000000000Bool dhall-1.19.1/tests/typecheck/success/prelude/Bool/odd/1A.dhall0000644000000000000000000000006313377175666022242 0ustar0000000000000000../../../../../../Prelude/Bool/odd [ True, False ] dhall-1.19.1/tests/typecheck/success/prelude/Bool/odd/1B.dhall0000644000000000000000000000000513377175666022237 0ustar0000000000000000Bool dhall-1.19.1/tests/typecheck/success/prelude/Bool/odd/2A.dhall0000644000000000000000000000005413377175666022243 0ustar0000000000000000../../../../../../Prelude/Bool/odd [ True ] dhall-1.19.1/tests/typecheck/success/prelude/Bool/odd/2B.dhall0000644000000000000000000000000513377175666022240 0ustar0000000000000000Bool dhall-1.19.1/tests/typecheck/success/prelude/Bool/odd/3A.dhall0000644000000000000000000000006413377175666022245 0ustar0000000000000000../../../../../../Prelude/Bool/odd ([] : List Bool) dhall-1.19.1/tests/typecheck/success/prelude/Bool/odd/3B.dhall0000644000000000000000000000000513377175666022241 0ustar0000000000000000Bool dhall-1.19.1/tests/typecheck/success/prelude/Bool/or/0000755000000000000000000000000013377175666020646 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Bool/or/0A.dhall0000644000000000000000000000007013377175666022111 0ustar0000000000000000../../../../../../Prelude/Bool/or [ True, False, True ] dhall-1.19.1/tests/typecheck/success/prelude/Bool/or/0B.dhall0000644000000000000000000000000513377175666022110 0ustar0000000000000000Bool dhall-1.19.1/tests/typecheck/success/prelude/Bool/or/1A.dhall0000644000000000000000000000006313377175666022114 0ustar0000000000000000../../../../../../Prelude/Bool/or ([] : List Bool) dhall-1.19.1/tests/typecheck/success/prelude/Bool/or/1B.dhall0000644000000000000000000000000513377175666022111 0ustar0000000000000000Bool dhall-1.19.1/tests/typecheck/success/prelude/Bool/show/0000755000000000000000000000000013377175666021206 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Bool/show/0A.dhall0000644000000000000000000000005113377175666022450 0ustar0000000000000000../../../../../../Prelude/Bool/show True dhall-1.19.1/tests/typecheck/success/prelude/Bool/show/0B.dhall0000644000000000000000000000000513377175666022450 0ustar0000000000000000Text dhall-1.19.1/tests/typecheck/success/prelude/Bool/show/1A.dhall0000644000000000000000000000005213377175666022452 0ustar0000000000000000../../../../../../Prelude/Bool/show False dhall-1.19.1/tests/typecheck/success/prelude/Bool/show/1B.dhall0000644000000000000000000000000513377175666022451 0ustar0000000000000000Text dhall-1.19.1/tests/typecheck/success/prelude/Double/0000755000000000000000000000000013377175666020545 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Double/show/0000755000000000000000000000000013377175666021525 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Double/show/0A.dhall0000644000000000000000000000005313377175666022771 0ustar0000000000000000../../../../../../Prelude/Double/show -3.1 dhall-1.19.1/tests/typecheck/success/prelude/Double/show/0B.dhall0000644000000000000000000000000513377175666022767 0ustar0000000000000000Text dhall-1.19.1/tests/typecheck/success/prelude/Double/show/1A.dhall0000644000000000000000000000005213377175666022771 0ustar0000000000000000../../../../../../Prelude/Double/show 0.4 dhall-1.19.1/tests/typecheck/success/prelude/Double/show/1B.dhall0000644000000000000000000000000513377175666022770 0ustar0000000000000000Text dhall-1.19.1/tests/typecheck/success/prelude/Integer/0000755000000000000000000000000013377175666020730 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Integer/show/0000755000000000000000000000000013377175666021710 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Integer/show/0A.dhall0000644000000000000000000000005213377175666023153 0ustar0000000000000000../../../../../../Prelude/Integer/show -3 dhall-1.19.1/tests/typecheck/success/prelude/Integer/show/0B.dhall0000644000000000000000000000000513377175666023152 0ustar0000000000000000Text dhall-1.19.1/tests/typecheck/success/prelude/Integer/show/1A.dhall0000644000000000000000000000005213377175666023154 0ustar0000000000000000../../../../../../Prelude/Integer/show +0 dhall-1.19.1/tests/typecheck/success/prelude/Integer/show/1B.dhall0000644000000000000000000000000513377175666023153 0ustar0000000000000000Text dhall-1.19.1/tests/typecheck/success/prelude/Integer/toDouble/0000755000000000000000000000000013377175666022505 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Integer/toDouble/0A.dhall0000644000000000000000000000005613377175666023754 0ustar0000000000000000../../../../../../Prelude/Integer/toDouble -3 dhall-1.19.1/tests/typecheck/success/prelude/Integer/toDouble/0B.dhall0000644000000000000000000000000713377175666023751 0ustar0000000000000000Double dhall-1.19.1/tests/typecheck/success/prelude/Integer/toDouble/1A.dhall0000644000000000000000000000005613377175666023755 0ustar0000000000000000../../../../../../Prelude/Integer/toDouble +2 dhall-1.19.1/tests/typecheck/success/prelude/Integer/toDouble/1B.dhall0000644000000000000000000000000713377175666023752 0ustar0000000000000000Double dhall-1.19.1/tests/typecheck/success/prelude/List/0000755000000000000000000000000013377175666020246 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/List/all/0000755000000000000000000000000013377175666021016 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/List/all/0A.dhall0000644000000000000000000000010413377175666022257 0ustar0000000000000000../../../../../../Prelude/List/all Natural Natural/even [ 2, 3, 5 ] dhall-1.19.1/tests/typecheck/success/prelude/List/all/0B.dhall0000644000000000000000000000000513377175666022260 0ustar0000000000000000Bool dhall-1.19.1/tests/typecheck/success/prelude/List/all/1A.dhall0000644000000000000000000000011413377175666022261 0ustar0000000000000000../../../../../../Prelude/List/all Natural Natural/even ([] : List Natural) dhall-1.19.1/tests/typecheck/success/prelude/List/all/1B.dhall0000644000000000000000000000000513377175666022261 0ustar0000000000000000Bool dhall-1.19.1/tests/typecheck/success/prelude/List/any/0000755000000000000000000000000013377175666021035 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/List/any/0A.dhall0000644000000000000000000000010413377175666022276 0ustar0000000000000000../../../../../../Prelude/List/any Natural Natural/even [ 2, 3, 5 ] dhall-1.19.1/tests/typecheck/success/prelude/List/any/0B.dhall0000644000000000000000000000000513377175666022277 0ustar0000000000000000Bool dhall-1.19.1/tests/typecheck/success/prelude/List/any/1A.dhall0000644000000000000000000000011413377175666022300 0ustar0000000000000000../../../../../../Prelude/List/any Natural Natural/even ([] : List Natural) dhall-1.19.1/tests/typecheck/success/prelude/List/any/1B.dhall0000644000000000000000000000000513377175666022300 0ustar0000000000000000Bool dhall-1.19.1/tests/typecheck/success/prelude/List/build/0000755000000000000000000000000013377175666021345 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/List/build/0A.dhall0000644000000000000000000000022713377175666022614 0ustar0000000000000000../../../../../../Prelude/List/build Text ( λ(list : Type) → λ(cons : Text → list → list) → λ(nil : list) → cons "ABC" (cons "DEF" nil) ) dhall-1.19.1/tests/typecheck/success/prelude/List/build/0B.dhall0000644000000000000000000000001213377175666022605 0ustar0000000000000000List Text dhall-1.19.1/tests/typecheck/success/prelude/List/build/1A.dhall0000644000000000000000000000017713377175666022621 0ustar0000000000000000../../../../../../Prelude/List/build Text ( λ(list : Type) → λ(cons : Text → list → list) → λ(nil : list) → nil ) dhall-1.19.1/tests/typecheck/success/prelude/List/build/1B.dhall0000644000000000000000000000001213377175666022606 0ustar0000000000000000List Text dhall-1.19.1/tests/typecheck/success/prelude/List/concat/0000755000000000000000000000000013377175666021515 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/List/concat/0A.dhall0000644000000000000000000000013213377175666022757 0ustar0000000000000000../../../../../../Prelude/List/concat Natural [ [ 0, 1, 2 ] , [ 3, 4 ] , [ 5, 6, 7, 8 ] ] dhall-1.19.1/tests/typecheck/success/prelude/List/concat/0B.dhall0000644000000000000000000000001513377175666022760 0ustar0000000000000000List Natural dhall-1.19.1/tests/typecheck/success/prelude/List/concat/1A.dhall0000644000000000000000000000015413377175666022764 0ustar0000000000000000../../../../../../Prelude/List/concat Natural [ [] : List Natural , [] : List Natural , [] : List Natural ] dhall-1.19.1/tests/typecheck/success/prelude/List/concat/1B.dhall0000644000000000000000000000001513377175666022761 0ustar0000000000000000List Natural dhall-1.19.1/tests/typecheck/success/prelude/List/concatMap/0000755000000000000000000000000013377175666022153 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/List/concatMap/0A.dhall0000644000000000000000000000014413377175666023420 0ustar0000000000000000../../../../../../Prelude/List/concatMap Natural Natural (λ(n : Natural) → [ n, n ]) [ 2, 3, 5 ] dhall-1.19.1/tests/typecheck/success/prelude/List/concatMap/0B.dhall0000644000000000000000000000001513377175666023416 0ustar0000000000000000List Natural dhall-1.19.1/tests/typecheck/success/prelude/List/concatMap/1A.dhall0000644000000000000000000000015413377175666023422 0ustar0000000000000000../../../../../../Prelude/List/concatMap Natural Natural (λ(n : Natural) → [ n, n ]) ([] : List Natural) dhall-1.19.1/tests/typecheck/success/prelude/List/concatMap/1B.dhall0000644000000000000000000000001513377175666023417 0ustar0000000000000000List Natural dhall-1.19.1/tests/typecheck/success/prelude/List/filter/0000755000000000000000000000000013377175666021533 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/List/filter/0A.dhall0000644000000000000000000000010713377175666022777 0ustar0000000000000000../../../../../../Prelude/List/filter Natural Natural/even [ 2, 3, 5 ] dhall-1.19.1/tests/typecheck/success/prelude/List/filter/0B.dhall0000644000000000000000000000001513377175666022776 0ustar0000000000000000List Natural dhall-1.19.1/tests/typecheck/success/prelude/List/filter/1A.dhall0000644000000000000000000000010613377175666022777 0ustar0000000000000000../../../../../../Prelude/List/filter Natural Natural/odd [ 2, 3, 5 ] dhall-1.19.1/tests/typecheck/success/prelude/List/filter/1B.dhall0000644000000000000000000000001513377175666022777 0ustar0000000000000000List Natural dhall-1.19.1/tests/typecheck/success/prelude/List/fold/0000755000000000000000000000000013377175666021172 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/List/fold/0A.dhall0000644000000000000000000000016213377175666022437 0ustar0000000000000000../../../../../../Prelude/List/fold Natural [ 2, 3, 5 ] Natural (λ(x : Natural) → λ(y : Natural) → x + y) 0 dhall-1.19.1/tests/typecheck/success/prelude/List/fold/0B.dhall0000644000000000000000000000001013377175666022430 0ustar0000000000000000Natural dhall-1.19.1/tests/typecheck/success/prelude/List/fold/1A.dhall0000644000000000000000000000022613377175666022441 0ustar0000000000000000 λ(nil : Natural) → ../../../../../../Prelude/List/fold Natural [ 2, 3, 5 ] Natural (λ(x : Natural) → λ(y : Natural) → x + y) nil dhall-1.19.1/tests/typecheck/success/prelude/List/fold/1B.dhall0000644000000000000000000000003713377175666022442 0ustar0000000000000000∀(nil : Natural) → Natural dhall-1.19.1/tests/typecheck/success/prelude/List/fold/2A.dhall0000644000000000000000000000023013377175666022435 0ustar0000000000000000 λ(list : Type) → λ(cons : Natural → list → list) → λ(nil : list) → ../../../../../../Prelude/List/fold Natural [ 2, 3, 5 ] list cons nil dhall-1.19.1/tests/typecheck/success/prelude/List/fold/2B.dhall0000644000000000000000000000013013377175666022435 0ustar0000000000000000∀(list : Type) → ∀(cons : Natural → list → list) → ∀(nil : list) → list dhall-1.19.1/tests/typecheck/success/prelude/List/generate/0000755000000000000000000000000013377175666022040 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/List/generate/0A.dhall0000644000000000000000000000007413377175666023307 0ustar0000000000000000../../../../../../Prelude/List/generate 5 Bool Natural/even dhall-1.19.1/tests/typecheck/success/prelude/List/generate/0B.dhall0000644000000000000000000000001213377175666023300 0ustar0000000000000000List Bool dhall-1.19.1/tests/typecheck/success/prelude/List/generate/1A.dhall0000644000000000000000000000007413377175666023310 0ustar0000000000000000../../../../../../Prelude/List/generate 0 Bool Natural/even dhall-1.19.1/tests/typecheck/success/prelude/List/generate/1B.dhall0000644000000000000000000000001213377175666023301 0ustar0000000000000000List Bool dhall-1.19.1/tests/typecheck/success/prelude/List/head/0000755000000000000000000000000013377175666021147 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/List/head/0A.dhall0000644000000000000000000000007013377175666022412 0ustar0000000000000000../../../../../../Prelude/List/head Natural [ 0, 1, 2 ] dhall-1.19.1/tests/typecheck/success/prelude/List/head/0B.dhall0000644000000000000000000000002113377175666022407 0ustar0000000000000000Optional Natural dhall-1.19.1/tests/typecheck/success/prelude/List/head/1A.dhall0000644000000000000000000000010013377175666022405 0ustar0000000000000000../../../../../../Prelude/List/head Natural ([] : List Natural) dhall-1.19.1/tests/typecheck/success/prelude/List/head/1B.dhall0000644000000000000000000000002113377175666022410 0ustar0000000000000000Optional Natural dhall-1.19.1/tests/typecheck/success/prelude/List/indexed/0000755000000000000000000000000013377175666021666 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/List/indexed/0A.dhall0000644000000000000000000000010213377175666023125 0ustar0000000000000000../../../../../../Prelude/List/indexed Bool [ True, False, True ] dhall-1.19.1/tests/typecheck/success/prelude/List/indexed/0B.dhall0000644000000000000000000000004713377175666023136 0ustar0000000000000000List { index : Natural, value : Bool } dhall-1.19.1/tests/typecheck/success/prelude/List/indexed/1A.dhall0000644000000000000000000000007513377175666023137 0ustar0000000000000000../../../../../../Prelude/List/indexed Bool ([] : List Bool) dhall-1.19.1/tests/typecheck/success/prelude/List/indexed/1B.dhall0000644000000000000000000000004713377175666023137 0ustar0000000000000000List { index : Natural, value : Bool } dhall-1.19.1/tests/typecheck/success/prelude/List/iterate/0000755000000000000000000000000013377175666021703 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/List/iterate/0A.dhall0000644000000000000000000000012013377175666023142 0ustar0000000000000000../../../../../../Prelude/List/iterate 10 Natural (λ(x : Natural) → x * 2) 1 dhall-1.19.1/tests/typecheck/success/prelude/List/iterate/0B.dhall0000644000000000000000000000001513377175666023146 0ustar0000000000000000List Natural dhall-1.19.1/tests/typecheck/success/prelude/List/iterate/1A.dhall0000644000000000000000000000011713377175666023151 0ustar0000000000000000../../../../../../Prelude/List/iterate 0 Natural (λ(x : Natural) → x * 2) 1 dhall-1.19.1/tests/typecheck/success/prelude/List/iterate/1B.dhall0000644000000000000000000000001513377175666023147 0ustar0000000000000000List Natural dhall-1.19.1/tests/typecheck/success/prelude/List/last/0000755000000000000000000000000013377175666021211 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/List/last/0A.dhall0000644000000000000000000000007013377175666022454 0ustar0000000000000000../../../../../../Prelude/List/last Natural [ 0, 1, 2 ] dhall-1.19.1/tests/typecheck/success/prelude/List/last/0B.dhall0000644000000000000000000000002113377175666022451 0ustar0000000000000000Optional Natural dhall-1.19.1/tests/typecheck/success/prelude/List/last/1A.dhall0000644000000000000000000000010013377175666022447 0ustar0000000000000000../../../../../../Prelude/List/last Natural ([] : List Natural) dhall-1.19.1/tests/typecheck/success/prelude/List/last/1B.dhall0000644000000000000000000000002113377175666022452 0ustar0000000000000000Optional Natural dhall-1.19.1/tests/typecheck/success/prelude/List/length/0000755000000000000000000000000013377175666021527 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/List/length/0A.dhall0000644000000000000000000000007213377175666022774 0ustar0000000000000000../../../../../../Prelude/List/length Natural [ 0, 1, 2 ] dhall-1.19.1/tests/typecheck/success/prelude/List/length/0B.dhall0000644000000000000000000000001013377175666022765 0ustar0000000000000000Natural dhall-1.19.1/tests/typecheck/success/prelude/List/length/1A.dhall0000644000000000000000000000010213377175666022767 0ustar0000000000000000../../../../../../Prelude/List/length Natural ([] : List Natural) dhall-1.19.1/tests/typecheck/success/prelude/List/length/1B.dhall0000644000000000000000000000001013377175666022766 0ustar0000000000000000Natural dhall-1.19.1/tests/typecheck/success/prelude/List/map/0000755000000000000000000000000013377175666021023 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/List/map/0A.dhall0000644000000000000000000000011113377175666022262 0ustar0000000000000000../../../../../../Prelude/List/map Natural Bool Natural/even [ 2, 3, 5 ] dhall-1.19.1/tests/typecheck/success/prelude/List/map/0B.dhall0000644000000000000000000000001213377175666022263 0ustar0000000000000000List Bool dhall-1.19.1/tests/typecheck/success/prelude/List/map/1A.dhall0000644000000000000000000000012113377175666022264 0ustar0000000000000000../../../../../../Prelude/List/map Natural Bool Natural/even ([] : List Natural) dhall-1.19.1/tests/typecheck/success/prelude/List/map/1B.dhall0000644000000000000000000000001213377175666022264 0ustar0000000000000000List Bool dhall-1.19.1/tests/typecheck/success/prelude/List/null/0000755000000000000000000000000013377175666021220 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/List/null/0A.dhall0000644000000000000000000000007013377175666022463 0ustar0000000000000000../../../../../../Prelude/List/null Natural [ 0, 1, 2 ] dhall-1.19.1/tests/typecheck/success/prelude/List/null/0B.dhall0000644000000000000000000000000513377175666022462 0ustar0000000000000000Bool dhall-1.19.1/tests/typecheck/success/prelude/List/null/1A.dhall0000644000000000000000000000010013377175666022456 0ustar0000000000000000../../../../../../Prelude/List/null Natural ([] : List Natural) dhall-1.19.1/tests/typecheck/success/prelude/List/null/1B.dhall0000644000000000000000000000000513377175666022463 0ustar0000000000000000Bool dhall-1.19.1/tests/typecheck/success/prelude/List/replicate/0000755000000000000000000000000013377175666022216 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/List/replicate/0A.dhall0000644000000000000000000000006513377175666023465 0ustar0000000000000000../../../../../../Prelude/List/replicate 9 Natural 1 dhall-1.19.1/tests/typecheck/success/prelude/List/replicate/0B.dhall0000644000000000000000000000001513377175666023461 0ustar0000000000000000List Natural dhall-1.19.1/tests/typecheck/success/prelude/List/replicate/1A.dhall0000644000000000000000000000006513377175666023466 0ustar0000000000000000../../../../../../Prelude/List/replicate 0 Natural 1 dhall-1.19.1/tests/typecheck/success/prelude/List/replicate/1B.dhall0000644000000000000000000000001513377175666023462 0ustar0000000000000000List Natural dhall-1.19.1/tests/typecheck/success/prelude/List/reverse/0000755000000000000000000000000013377175666021721 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/List/reverse/0A.dhall0000644000000000000000000000007313377175666023167 0ustar0000000000000000../../../../../../Prelude/List/reverse Natural [ 0, 1, 2 ] dhall-1.19.1/tests/typecheck/success/prelude/List/reverse/0B.dhall0000644000000000000000000000001513377175666023164 0ustar0000000000000000List Natural dhall-1.19.1/tests/typecheck/success/prelude/List/reverse/1A.dhall0000644000000000000000000000010313377175666023162 0ustar0000000000000000../../../../../../Prelude/List/reverse Natural ([] : List Natural) dhall-1.19.1/tests/typecheck/success/prelude/List/reverse/1B.dhall0000644000000000000000000000001513377175666023165 0ustar0000000000000000List Natural dhall-1.19.1/tests/typecheck/success/prelude/List/shifted/0000755000000000000000000000000013377175666021674 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/List/shifted/0A.dhall0000644000000000000000000000053513377175666023145 0ustar0000000000000000../../../../../../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-1.19.1/tests/typecheck/success/prelude/List/shifted/0B.dhall0000644000000000000000000000004713377175666023144 0ustar0000000000000000List { index : Natural, value : Bool } dhall-1.19.1/tests/typecheck/success/prelude/List/shifted/1A.dhall0000644000000000000000000000014113377175666023137 0ustar0000000000000000../../../../../../Prelude/List/shifted Bool ([] : List (List { index : Natural, value : Bool })) dhall-1.19.1/tests/typecheck/success/prelude/List/shifted/1B.dhall0000644000000000000000000000004713377175666023145 0ustar0000000000000000List { index : Natural, value : Bool } dhall-1.19.1/tests/typecheck/success/prelude/List/unzip/0000755000000000000000000000000013377175666021413 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/List/unzip/0A.dhall0000644000000000000000000000020613377175666022657 0ustar0000000000000000../../../../../../Prelude/List/unzip Text Bool [ { _1 = "ABC", _2 = True } , { _1 = "DEF", _2 = False } , { _1 = "GHI", _2 = True } ] dhall-1.19.1/tests/typecheck/success/prelude/List/unzip/0B.dhall0000644000000000000000000000004313377175666022657 0ustar0000000000000000{ _1 : List Text, _2 : List Bool } dhall-1.19.1/tests/typecheck/success/prelude/List/unzip/1A.dhall0000644000000000000000000000012413377175666022657 0ustar0000000000000000../../../../../../Prelude/List/unzip Text Bool ([] : List { _1 : Text, _2 : Bool }) dhall-1.19.1/tests/typecheck/success/prelude/List/unzip/1B.dhall0000644000000000000000000000004313377175666022660 0ustar0000000000000000{ _1 : List Text, _2 : List Bool } dhall-1.19.1/tests/typecheck/success/prelude/Monoid/0000755000000000000000000000000013377175666020560 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Monoid/00A.dhall0000644000000000000000000000006213377175666022104 0ustar0000000000000000(../../../../../Prelude/package.dhall).`Bool`.and dhall-1.19.1/tests/typecheck/success/prelude/Monoid/00B.dhall0000644000000000000000000000004313377175666022104 0ustar0000000000000000../../../../../Prelude/Monoid Bool dhall-1.19.1/tests/typecheck/success/prelude/Monoid/01A.dhall0000644000000000000000000000006113377175666022104 0ustar0000000000000000(../../../../../Prelude/package.dhall).`Bool`.or dhall-1.19.1/tests/typecheck/success/prelude/Monoid/01B.dhall0000644000000000000000000000004313377175666022105 0ustar0000000000000000../../../../../Prelude/Monoid Bool dhall-1.19.1/tests/typecheck/success/prelude/Monoid/02A.dhall0000644000000000000000000000006313377175666022107 0ustar0000000000000000(../../../../../Prelude/package.dhall).`Bool`.even dhall-1.19.1/tests/typecheck/success/prelude/Monoid/02B.dhall0000644000000000000000000000004313377175666022106 0ustar0000000000000000../../../../../Prelude/Monoid Bool dhall-1.19.1/tests/typecheck/success/prelude/Monoid/03A.dhall0000644000000000000000000000006213377175666022107 0ustar0000000000000000(../../../../../Prelude/package.dhall).`Bool`.odd dhall-1.19.1/tests/typecheck/success/prelude/Monoid/03B.dhall0000644000000000000000000000004313377175666022107 0ustar0000000000000000../../../../../Prelude/Monoid Bool dhall-1.19.1/tests/typecheck/success/prelude/Monoid/04A.dhall0000644000000000000000000000006513377175666022113 0ustar0000000000000000(../../../../../Prelude/package.dhall).`List`.concat dhall-1.19.1/tests/typecheck/success/prelude/Monoid/04B.dhall0000644000000000000000000000007113377175666022111 0ustar0000000000000000∀(a : Type) → ../../../../../Prelude/Monoid (List a) dhall-1.19.1/tests/typecheck/success/prelude/Monoid/05A.dhall0000644000000000000000000000006613377175666022115 0ustar0000000000000000(../../../../../Prelude/package.dhall).`List`.shifted dhall-1.19.1/tests/typecheck/success/prelude/Monoid/05B.dhall0000644000000000000000000000012613377175666022113 0ustar0000000000000000∀(a : Type) → ../../../../../Prelude/Monoid (List { index : Natural, value : a }) dhall-1.19.1/tests/typecheck/success/prelude/Monoid/06A.dhall0000644000000000000000000000006513377175666022115 0ustar0000000000000000(../../../../../Prelude/package.dhall).`Natural`.sum dhall-1.19.1/tests/typecheck/success/prelude/Monoid/06B.dhall0000644000000000000000000000004613377175666022115 0ustar0000000000000000../../../../../Prelude/Monoid Natural dhall-1.19.1/tests/typecheck/success/prelude/Monoid/07A.dhall0000644000000000000000000000007113377175666022113 0ustar0000000000000000(../../../../../Prelude/package.dhall).`Natural`.product dhall-1.19.1/tests/typecheck/success/prelude/Monoid/07B.dhall0000644000000000000000000000004613377175666022116 0ustar0000000000000000../../../../../Prelude/Monoid Natural dhall-1.19.1/tests/typecheck/success/prelude/Monoid/08A.dhall0000644000000000000000000000006713377175666022121 0ustar0000000000000000(../../../../../Prelude/package.dhall).`Optional`.head dhall-1.19.1/tests/typecheck/success/prelude/Monoid/08B.dhall0000644000000000000000000000007513377175666022121 0ustar0000000000000000∀(a : Type) → ../../../../../Prelude/Monoid (Optional a) dhall-1.19.1/tests/typecheck/success/prelude/Monoid/09A.dhall0000644000000000000000000000006713377175666022122 0ustar0000000000000000(../../../../../Prelude/package.dhall).`Optional`.last dhall-1.19.1/tests/typecheck/success/prelude/Monoid/09B.dhall0000644000000000000000000000007513377175666022122 0ustar0000000000000000∀(a : Type) → ../../../../../Prelude/Monoid (Optional a) dhall-1.19.1/tests/typecheck/success/prelude/Monoid/10A.dhall0000644000000000000000000000006513377175666022110 0ustar0000000000000000(../../../../../Prelude/package.dhall).`Text`.concat dhall-1.19.1/tests/typecheck/success/prelude/Monoid/10B.dhall0000644000000000000000000000004313377175666022105 0ustar0000000000000000../../../../../Prelude/Monoid Text dhall-1.19.1/tests/typecheck/success/prelude/Natural/0000755000000000000000000000000013377175666020741 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Natural/build/0000755000000000000000000000000013377175666022040 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Natural/build/0A.dhall0000644000000000000000000000022513377175666023305 0ustar0000000000000000../../../../../../Prelude/Natural/build ( λ(natural : Type) → λ(succ : natural → natural) → λ(zero : natural) → succ (succ (succ zero)) ) dhall-1.19.1/tests/typecheck/success/prelude/Natural/build/0B.dhall0000644000000000000000000000001013377175666023276 0ustar0000000000000000Natural dhall-1.19.1/tests/typecheck/success/prelude/Natural/build/1A.dhall0000644000000000000000000000020213377175666023301 0ustar0000000000000000../../../../../../Prelude/Natural/build ( λ(natural : Type) → λ(succ : natural → natural) → λ(zero : natural) → zero ) dhall-1.19.1/tests/typecheck/success/prelude/Natural/build/1B.dhall0000644000000000000000000000001013377175666023277 0ustar0000000000000000Natural dhall-1.19.1/tests/typecheck/success/prelude/Natural/enumerate/0000755000000000000000000000000013377175666022726 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Natural/enumerate/0A.dhall0000644000000000000000000000005713377175666024176 0ustar0000000000000000../../../../../../Prelude/Natural/enumerate 10 dhall-1.19.1/tests/typecheck/success/prelude/Natural/enumerate/0B.dhall0000644000000000000000000000001513377175666024171 0ustar0000000000000000List Natural dhall-1.19.1/tests/typecheck/success/prelude/Natural/enumerate/1A.dhall0000644000000000000000000000005613377175666024176 0ustar0000000000000000../../../../../../Prelude/Natural/enumerate 0 dhall-1.19.1/tests/typecheck/success/prelude/Natural/enumerate/1B.dhall0000644000000000000000000000001513377175666024172 0ustar0000000000000000List Natural dhall-1.19.1/tests/typecheck/success/prelude/Natural/even/0000755000000000000000000000000013377175666021676 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Natural/even/0A.dhall0000644000000000000000000000005113377175666023140 0ustar0000000000000000../../../../../../Prelude/Natural/even 3 dhall-1.19.1/tests/typecheck/success/prelude/Natural/even/0B.dhall0000644000000000000000000000000513377175666023140 0ustar0000000000000000Bool dhall-1.19.1/tests/typecheck/success/prelude/Natural/even/1A.dhall0000644000000000000000000000005113377175666023141 0ustar0000000000000000../../../../../../Prelude/Natural/even 0 dhall-1.19.1/tests/typecheck/success/prelude/Natural/even/1B.dhall0000644000000000000000000000000513377175666023141 0ustar0000000000000000Bool dhall-1.19.1/tests/typecheck/success/prelude/Natural/fold/0000755000000000000000000000000013377175666021665 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Natural/fold/0A.dhall0000644000000000000000000000011713377175666023132 0ustar0000000000000000../../../../../../Prelude/Natural/fold 3 Natural (λ(x : Natural) → 5 * x) 1 dhall-1.19.1/tests/typecheck/success/prelude/Natural/fold/0B.dhall0000644000000000000000000000001013377175666023123 0ustar0000000000000000Natural dhall-1.19.1/tests/typecheck/success/prelude/Natural/fold/1A.dhall0000644000000000000000000000015113377175666023131 0ustar0000000000000000λ(zero : Natural) → ../../../../../../Prelude/Natural/fold 3 Natural (λ(x : Natural) → 5 * x) zero dhall-1.19.1/tests/typecheck/success/prelude/Natural/fold/1B.dhall0000644000000000000000000000004013377175666023127 0ustar0000000000000000∀(zero : Natural) → Natural dhall-1.19.1/tests/typecheck/success/prelude/Natural/fold/2A.dhall0000644000000000000000000000021613377175666023134 0ustar0000000000000000 λ(natural : Type) → λ(succ : natural → natural) → λ(zero : natural) → ../../../../../../Prelude/Natural/fold 3 natural succ zero dhall-1.19.1/tests/typecheck/success/prelude/Natural/fold/2B.dhall0000644000000000000000000000013413377175666023134 0ustar0000000000000000∀(natural : Type) → ∀(succ : natural → natural) → ∀(zero : natural) → natural dhall-1.19.1/tests/typecheck/success/prelude/Natural/isZero/0000755000000000000000000000000013377175666022214 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Natural/isZero/0A.dhall0000644000000000000000000000005313377175666023460 0ustar0000000000000000../../../../../../Prelude/Natural/isZero 2 dhall-1.19.1/tests/typecheck/success/prelude/Natural/isZero/0B.dhall0000644000000000000000000000000513377175666023456 0ustar0000000000000000Bool dhall-1.19.1/tests/typecheck/success/prelude/Natural/isZero/1A.dhall0000644000000000000000000000005313377175666023461 0ustar0000000000000000../../../../../../Prelude/Natural/isZero 0 dhall-1.19.1/tests/typecheck/success/prelude/Natural/isZero/1B.dhall0000644000000000000000000000000513377175666023457 0ustar0000000000000000Bool dhall-1.19.1/tests/typecheck/success/prelude/Natural/odd/0000755000000000000000000000000013377175666021507 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Natural/odd/0A.dhall0000644000000000000000000000005013377175666022750 0ustar0000000000000000../../../../../../Prelude/Natural/odd 3 dhall-1.19.1/tests/typecheck/success/prelude/Natural/odd/0B.dhall0000644000000000000000000000000513377175666022751 0ustar0000000000000000Bool dhall-1.19.1/tests/typecheck/success/prelude/Natural/odd/1A.dhall0000644000000000000000000000005013377175666022751 0ustar0000000000000000../../../../../../Prelude/Natural/odd 0 dhall-1.19.1/tests/typecheck/success/prelude/Natural/odd/1B.dhall0000644000000000000000000000000513377175666022752 0ustar0000000000000000Bool dhall-1.19.1/tests/typecheck/success/prelude/Natural/product/0000755000000000000000000000000013377175666022421 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Natural/product/0A.dhall0000644000000000000000000000006613377175666023671 0ustar0000000000000000../../../../../../Prelude/Natural/product [ 2, 3, 5 ] dhall-1.19.1/tests/typecheck/success/prelude/Natural/product/0B.dhall0000644000000000000000000000001013377175666023657 0ustar0000000000000000Natural dhall-1.19.1/tests/typecheck/success/prelude/Natural/product/1A.dhall0000644000000000000000000000007613377175666023673 0ustar0000000000000000../../../../../../Prelude/Natural/product ([] : List Natural) dhall-1.19.1/tests/typecheck/success/prelude/Natural/product/1B.dhall0000644000000000000000000000001013377175666023660 0ustar0000000000000000Natural dhall-1.19.1/tests/typecheck/success/prelude/Natural/show/0000755000000000000000000000000013377175666021721 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Natural/show/0A.dhall0000644000000000000000000000005113377175666023163 0ustar0000000000000000../../../../../../Prelude/Natural/show 3 dhall-1.19.1/tests/typecheck/success/prelude/Natural/show/0B.dhall0000644000000000000000000000000513377175666023163 0ustar0000000000000000Text dhall-1.19.1/tests/typecheck/success/prelude/Natural/show/1A.dhall0000644000000000000000000000005113377175666023164 0ustar0000000000000000../../../../../../Prelude/Natural/show 0 dhall-1.19.1/tests/typecheck/success/prelude/Natural/show/1B.dhall0000644000000000000000000000000513377175666023164 0ustar0000000000000000Text dhall-1.19.1/tests/typecheck/success/prelude/Natural/sum/0000755000000000000000000000000013377175666021545 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Natural/sum/0A.dhall0000644000000000000000000000006213377175666023011 0ustar0000000000000000../../../../../../Prelude/Natural/sum [ 2, 3, 5 ] dhall-1.19.1/tests/typecheck/success/prelude/Natural/sum/0B.dhall0000644000000000000000000000001013377175666023003 0ustar0000000000000000Natural dhall-1.19.1/tests/typecheck/success/prelude/Natural/sum/1A.dhall0000644000000000000000000000007213377175666023013 0ustar0000000000000000../../../../../../Prelude/Natural/sum ([] : List Natural) dhall-1.19.1/tests/typecheck/success/prelude/Natural/sum/1B.dhall0000644000000000000000000000001013377175666023004 0ustar0000000000000000Natural dhall-1.19.1/tests/typecheck/success/prelude/Natural/toDouble/0000755000000000000000000000000013377175666022516 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Natural/toDouble/0A.dhall0000644000000000000000000000005513377175666023764 0ustar0000000000000000../../../../../../Prelude/Natural/toDouble 3 dhall-1.19.1/tests/typecheck/success/prelude/Natural/toDouble/0B.dhall0000644000000000000000000000000713377175666023762 0ustar0000000000000000Double dhall-1.19.1/tests/typecheck/success/prelude/Natural/toDouble/1A.dhall0000644000000000000000000000005513377175666023765 0ustar0000000000000000../../../../../../Prelude/Natural/toDouble 0 dhall-1.19.1/tests/typecheck/success/prelude/Natural/toDouble/1B.dhall0000644000000000000000000000000713377175666023763 0ustar0000000000000000Double dhall-1.19.1/tests/typecheck/success/prelude/Natural/toInteger/0000755000000000000000000000000013377175666022701 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Natural/toInteger/0A.dhall0000644000000000000000000000005613377175666024150 0ustar0000000000000000../../../../../../Prelude/Natural/toInteger 3 dhall-1.19.1/tests/typecheck/success/prelude/Natural/toInteger/0B.dhall0000644000000000000000000000001013377175666024137 0ustar0000000000000000Integer dhall-1.19.1/tests/typecheck/success/prelude/Natural/toInteger/1A.dhall0000644000000000000000000000005613377175666024151 0ustar0000000000000000../../../../../../Prelude/Natural/toInteger 0 dhall-1.19.1/tests/typecheck/success/prelude/Natural/toInteger/1B.dhall0000644000000000000000000000001013377175666024140 0ustar0000000000000000Integer dhall-1.19.1/tests/typecheck/success/prelude/Optional/0000755000000000000000000000000013377175666021120 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Optional/all/0000755000000000000000000000000013377175666021670 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Optional/all/0A.dhall0000644000000000000000000000010513377175666023132 0ustar0000000000000000../../../../../../Prelude/Optional/all Natural Natural/even (Some 3) dhall-1.19.1/tests/typecheck/success/prelude/Optional/all/0B.dhall0000644000000000000000000000000513377175666023132 0ustar0000000000000000Bool dhall-1.19.1/tests/typecheck/success/prelude/Optional/all/1A.dhall0000644000000000000000000000011313377175666023132 0ustar0000000000000000../../../../../../Prelude/Optional/all Natural Natural/even (None Natural) dhall-1.19.1/tests/typecheck/success/prelude/Optional/all/1B.dhall0000644000000000000000000000000513377175666023133 0ustar0000000000000000Bool dhall-1.19.1/tests/typecheck/success/prelude/Optional/any/0000755000000000000000000000000013377175666021707 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Optional/any/0A.dhall0000644000000000000000000000010513377175666023151 0ustar0000000000000000../../../../../../Prelude/Optional/any Natural Natural/even (Some 2) dhall-1.19.1/tests/typecheck/success/prelude/Optional/any/0B.dhall0000644000000000000000000000000513377175666023151 0ustar0000000000000000Bool dhall-1.19.1/tests/typecheck/success/prelude/Optional/any/1A.dhall0000644000000000000000000000011313377175666023151 0ustar0000000000000000../../../../../../Prelude/Optional/any Natural Natural/even (None Natural) dhall-1.19.1/tests/typecheck/success/prelude/Optional/any/1B.dhall0000644000000000000000000000000513377175666023152 0ustar0000000000000000Bool dhall-1.19.1/tests/typecheck/success/prelude/Optional/build/0000755000000000000000000000000013377175666022217 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Optional/build/0A.dhall0000644000000000000000000000022013377175666023457 0ustar0000000000000000../../../../../../Prelude/Optional/build Natural ( λ(optional : Type) → λ(some : Natural → optional) → λ(none : optional) → some 1 ) dhall-1.19.1/tests/typecheck/success/prelude/Optional/build/0B.dhall0000644000000000000000000000002113377175666023457 0ustar0000000000000000Optional Natural dhall-1.19.1/tests/typecheck/success/prelude/Optional/build/1A.dhall0000644000000000000000000000021613377175666023465 0ustar0000000000000000../../../../../../Prelude/Optional/build Natural ( λ(optional : Type) → λ(some : Natural → optional) → λ(none : optional) → none ) dhall-1.19.1/tests/typecheck/success/prelude/Optional/build/1B.dhall0000644000000000000000000000002113377175666023460 0ustar0000000000000000Optional Natural dhall-1.19.1/tests/typecheck/success/prelude/Optional/concat/0000755000000000000000000000000013377175666022367 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Optional/concat/0A.dhall0000644000000000000000000000010213377175666023626 0ustar0000000000000000../../../../../../Prelude/Optional/concat Natural (Some (Some 1)) dhall-1.19.1/tests/typecheck/success/prelude/Optional/concat/0B.dhall0000644000000000000000000000002113377175666023627 0ustar0000000000000000Optional Natural dhall-1.19.1/tests/typecheck/success/prelude/Optional/concat/1A.dhall0000644000000000000000000000011013377175666023626 0ustar0000000000000000../../../../../../Prelude/Optional/concat Natural (Some (None Natural)) dhall-1.19.1/tests/typecheck/success/prelude/Optional/concat/1B.dhall0000644000000000000000000000002113377175666023630 0ustar0000000000000000Optional Natural dhall-1.19.1/tests/typecheck/success/prelude/Optional/concat/2A.dhall0000644000000000000000000000011413377175666023633 0ustar0000000000000000../../../../../../Prelude/Optional/concat Natural (None (Optional Natural)) dhall-1.19.1/tests/typecheck/success/prelude/Optional/concat/2B.dhall0000644000000000000000000000002113377175666023631 0ustar0000000000000000Optional Natural dhall-1.19.1/tests/typecheck/success/prelude/Optional/filter/0000755000000000000000000000000013377175666022405 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Optional/filter/0A.dhall0000644000000000000000000000011013377175666023643 0ustar0000000000000000../../../../../../Prelude/Optional/filter Natural Natural/even (Some 2) dhall-1.19.1/tests/typecheck/success/prelude/Optional/filter/0B.dhall0000644000000000000000000000002113377175666023645 0ustar0000000000000000Optional Natural dhall-1.19.1/tests/typecheck/success/prelude/Optional/filter/1A.dhall0000644000000000000000000000010713377175666023652 0ustar0000000000000000../../../../../../Prelude/Optional/filter Natural Natural/odd (Some 2) dhall-1.19.1/tests/typecheck/success/prelude/Optional/filter/1B.dhall0000644000000000000000000000002113377175666023646 0ustar0000000000000000Optional Natural dhall-1.19.1/tests/typecheck/success/prelude/Optional/fold/0000755000000000000000000000000013377175666022044 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Optional/fold/0A.dhall0000644000000000000000000000013313377175666023307 0ustar0000000000000000../../../../../../Prelude/Optional/fold Natural (Some 2) Natural (λ(x : Natural) → x) 0 dhall-1.19.1/tests/typecheck/success/prelude/Optional/fold/0B.dhall0000644000000000000000000000001013377175666023302 0ustar0000000000000000Natural dhall-1.19.1/tests/typecheck/success/prelude/Optional/fold/1A.dhall0000644000000000000000000000014113377175666023307 0ustar0000000000000000../../../../../../Prelude/Optional/fold Natural (None Natural) Natural (λ(x : Natural) → x) 0 dhall-1.19.1/tests/typecheck/success/prelude/Optional/fold/1B.dhall0000644000000000000000000000001013377175666023303 0ustar0000000000000000Natural dhall-1.19.1/tests/typecheck/success/prelude/Optional/head/0000755000000000000000000000000013377175666022021 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Optional/head/0A.dhall0000644000000000000000000000012113377175666023261 0ustar0000000000000000../../../../../../Prelude/Optional/head Natural [ None Natural, Some 1, Some 2 ] dhall-1.19.1/tests/typecheck/success/prelude/Optional/head/0B.dhall0000644000000000000000000000002113377175666023261 0ustar0000000000000000Optional Natural dhall-1.19.1/tests/typecheck/success/prelude/Optional/head/1A.dhall0000644000000000000000000000011713377175666023267 0ustar0000000000000000../../../../../../Prelude/Optional/head Natural [ None Natural, None Natural ] dhall-1.19.1/tests/typecheck/success/prelude/Optional/head/1B.dhall0000644000000000000000000000002113377175666023262 0ustar0000000000000000Optional Natural dhall-1.19.1/tests/typecheck/success/prelude/Optional/head/2A.dhall0000644000000000000000000000011713377175666023270 0ustar0000000000000000../../../../../../Prelude/Optional/head Natural ([] : List (Optional Natural)) dhall-1.19.1/tests/typecheck/success/prelude/Optional/head/2B.dhall0000644000000000000000000000002113377175666023263 0ustar0000000000000000Optional Natural dhall-1.19.1/tests/typecheck/success/prelude/Optional/last/0000755000000000000000000000000013377175666022063 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Optional/last/0A.dhall0000644000000000000000000000012113377175666023323 0ustar0000000000000000../../../../../../Prelude/Optional/last Natural [ None Natural, Some 1, Some 2 ] dhall-1.19.1/tests/typecheck/success/prelude/Optional/last/0B.dhall0000644000000000000000000000002113377175666023323 0ustar0000000000000000Optional Natural dhall-1.19.1/tests/typecheck/success/prelude/Optional/last/1A.dhall0000644000000000000000000000011713377175666023331 0ustar0000000000000000../../../../../../Prelude/Optional/last Natural [ None Natural, None Natural ] dhall-1.19.1/tests/typecheck/success/prelude/Optional/last/1B.dhall0000644000000000000000000000002113377175666023324 0ustar0000000000000000Optional Natural dhall-1.19.1/tests/typecheck/success/prelude/Optional/last/2A.dhall0000644000000000000000000000011713377175666023332 0ustar0000000000000000../../../../../../Prelude/Optional/last Natural ([] : List (Optional Natural)) dhall-1.19.1/tests/typecheck/success/prelude/Optional/last/2B.dhall0000644000000000000000000000002113377175666023325 0ustar0000000000000000Optional Natural dhall-1.19.1/tests/typecheck/success/prelude/Optional/length/0000755000000000000000000000000013377175666022401 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Optional/length/0A.dhall0000644000000000000000000000007313377175666023647 0ustar0000000000000000../../../../../../Prelude/Optional/length Natural (Some 2) dhall-1.19.1/tests/typecheck/success/prelude/Optional/length/0B.dhall0000644000000000000000000000001013377175666023637 0ustar0000000000000000Natural dhall-1.19.1/tests/typecheck/success/prelude/Optional/length/1A.dhall0000644000000000000000000000010113377175666023640 0ustar0000000000000000../../../../../../Prelude/Optional/length Natural (None Natural) dhall-1.19.1/tests/typecheck/success/prelude/Optional/length/1B.dhall0000644000000000000000000000001013377175666023640 0ustar0000000000000000Natural dhall-1.19.1/tests/typecheck/success/prelude/Optional/map/0000755000000000000000000000000013377175666021675 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Optional/map/0A.dhall0000644000000000000000000000011213377175666023135 0ustar0000000000000000../../../../../../Prelude/Optional/map Natural Bool Natural/even (Some 3) dhall-1.19.1/tests/typecheck/success/prelude/Optional/map/0B.dhall0000644000000000000000000000001613377175666023141 0ustar0000000000000000Optional Bool dhall-1.19.1/tests/typecheck/success/prelude/Optional/map/1A.dhall0000644000000000000000000000012013377175666023135 0ustar0000000000000000../../../../../../Prelude/Optional/map Natural Bool Natural/even (None Natural) dhall-1.19.1/tests/typecheck/success/prelude/Optional/map/1B.dhall0000644000000000000000000000001613377175666023142 0ustar0000000000000000Optional Bool dhall-1.19.1/tests/typecheck/success/prelude/Optional/null/0000755000000000000000000000000013377175666022072 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Optional/null/0A.dhall0000644000000000000000000000007113377175666023336 0ustar0000000000000000../../../../../../Prelude/Optional/null Natural (Some 2) dhall-1.19.1/tests/typecheck/success/prelude/Optional/null/0B.dhall0000644000000000000000000000000513377175666023334 0ustar0000000000000000Bool dhall-1.19.1/tests/typecheck/success/prelude/Optional/null/1A.dhall0000644000000000000000000000007713377175666023345 0ustar0000000000000000../../../../../../Prelude/Optional/null Natural (None Natural) dhall-1.19.1/tests/typecheck/success/prelude/Optional/null/1B.dhall0000644000000000000000000000000513377175666023335 0ustar0000000000000000Bool dhall-1.19.1/tests/typecheck/success/prelude/Optional/toList/0000755000000000000000000000000013377175666022376 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Optional/toList/0A.dhall0000644000000000000000000000007313377175666023644 0ustar0000000000000000../../../../../../Prelude/Optional/toList Natural (Some 1) dhall-1.19.1/tests/typecheck/success/prelude/Optional/toList/0B.dhall0000644000000000000000000000001513377175666023641 0ustar0000000000000000List Natural dhall-1.19.1/tests/typecheck/success/prelude/Optional/toList/1A.dhall0000644000000000000000000000010113377175666023635 0ustar0000000000000000../../../../../../Prelude/Optional/toList Natural (None Natural) dhall-1.19.1/tests/typecheck/success/prelude/Optional/toList/1B.dhall0000644000000000000000000000001513377175666023642 0ustar0000000000000000List Natural dhall-1.19.1/tests/typecheck/success/prelude/Optional/unzip/0000755000000000000000000000000013377175666022265 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Optional/unzip/0A.dhall0000644000000000000000000000012413377175666023530 0ustar0000000000000000../../../../../../Prelude/Optional/unzip Text Bool (Some { _1 = "ABC", _2 = True }) dhall-1.19.1/tests/typecheck/success/prelude/Optional/unzip/0B.dhall0000644000000000000000000000005313377175666023532 0ustar0000000000000000{ _1 : Optional Text, _2 : Optional Bool } dhall-1.19.1/tests/typecheck/success/prelude/Optional/unzip/1A.dhall0000644000000000000000000000012313377175666023530 0ustar0000000000000000../../../../../../Prelude/Optional/unzip Text Bool (None { _1 : Text, _2 : Bool }) dhall-1.19.1/tests/typecheck/success/prelude/Optional/unzip/1B.dhall0000644000000000000000000000005313377175666023533 0ustar0000000000000000{ _1 : Optional Text, _2 : Optional Bool } dhall-1.19.1/tests/typecheck/success/prelude/Text/0000755000000000000000000000000013377175666020257 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Text/concat/0000755000000000000000000000000013377175666021526 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Text/concat/0A.dhall0000644000000000000000000000007613377175666022777 0ustar0000000000000000../../../../../../Prelude/Text/concat [ "ABC", "DEF", "GHI" ] dhall-1.19.1/tests/typecheck/success/prelude/Text/concat/0B.dhall0000644000000000000000000000000513377175666022770 0ustar0000000000000000Text dhall-1.19.1/tests/typecheck/success/prelude/Text/concat/1A.dhall0000644000000000000000000000006713377175666023000 0ustar0000000000000000../../../../../../Prelude/Text/concat ([] : List Text) dhall-1.19.1/tests/typecheck/success/prelude/Text/concat/1B.dhall0000644000000000000000000000000513377175666022771 0ustar0000000000000000Text dhall-1.19.1/tests/typecheck/success/prelude/Text/concatMap/0000755000000000000000000000000013377175666022164 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Text/concatMap/0A.dhall0000644000000000000000000000015013377175666023426 0ustar0000000000000000../../../../../../Prelude/Text/concatMap Natural (λ(n : Natural) → "${Natural/show n} ") [ 0, 1, 2 ] dhall-1.19.1/tests/typecheck/success/prelude/Text/concatMap/0B.dhall0000644000000000000000000000000513377175666023426 0ustar0000000000000000Text dhall-1.19.1/tests/typecheck/success/prelude/Text/concatMap/1A.dhall0000644000000000000000000000016013377175666023430 0ustar0000000000000000../../../../../../Prelude/Text/concatMap Natural (λ(n : Natural) → "${Natural/show n} ") ([] : List Natural) dhall-1.19.1/tests/typecheck/success/prelude/Text/concatMap/1B.dhall0000644000000000000000000000000513377175666023427 0ustar0000000000000000Text dhall-1.19.1/tests/typecheck/success/prelude/Text/concatMapSep/0000755000000000000000000000000013377175666022634 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Text/concatMapSep/0A.dhall0000644000000000000000000000012213377175666024075 0ustar0000000000000000../../../../../../Prelude/Text/concatMapSep ", " Natural Natural/show [ 0, 1, 2 ] dhall-1.19.1/tests/typecheck/success/prelude/Text/concatMapSep/0B.dhall0000644000000000000000000000000513377175666024076 0ustar0000000000000000Text dhall-1.19.1/tests/typecheck/success/prelude/Text/concatMapSep/1A.dhall0000644000000000000000000000013213377175666024077 0ustar0000000000000000../../../../../../Prelude/Text/concatMapSep ", " Natural Natural/show ([] : List Natural) dhall-1.19.1/tests/typecheck/success/prelude/Text/concatMapSep/1B.dhall0000644000000000000000000000000513377175666024077 0ustar0000000000000000Text dhall-1.19.1/tests/typecheck/success/prelude/Text/concatSep/0000755000000000000000000000000013377175666022176 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/prelude/Text/concatSep/0A.dhall0000644000000000000000000000010613377175666023441 0ustar0000000000000000../../../../../../Prelude/Text/concatSep ", " [ "ABC", "DEF", "GHI" ] dhall-1.19.1/tests/typecheck/success/prelude/Text/concatSep/0B.dhall0000644000000000000000000000000513377175666023440 0ustar0000000000000000Text dhall-1.19.1/tests/typecheck/success/prelude/Text/concatSep/1A.dhall0000644000000000000000000000007713377175666023451 0ustar0000000000000000../../../../../../Prelude/Text/concatSep ", " ([] : List Text) dhall-1.19.1/tests/typecheck/success/prelude/Text/concatSep/1B.dhall0000644000000000000000000000000513377175666023441 0ustar0000000000000000Text dhall-1.19.1/tests/typecheck/success/simple/0000755000000000000000000000000013377175666017164 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/simple/alternativesAreTypesA.dhall0000644000000000000000000000003713377175666024451 0ustar0000000000000000< Left = List | Right : Type > dhall-1.19.1/tests/typecheck/success/simple/alternativesAreTypesB.dhall0000644000000000000000000000005013377175666024445 0ustar0000000000000000< Left : Type → Type | Right : Type > dhall-1.19.1/tests/typecheck/success/simple/anonymousFunctionsInTypesA.dhall0000644000000000000000000000031413377175666025526 0ustar0000000000000000 let anonymousFunction = λ(a : Type) → List a in λ(HigherOrderType : (Type → Type) → Type) → λ(x : HigherOrderType anonymousFunction) → (x : HigherOrderType anonymousFunction) dhall-1.19.1/tests/typecheck/success/simple/anonymousFunctionsInTypesB.dhall0000644000000000000000000000023013377175666025524 0ustar0000000000000000 ∀(HigherOrderType : (Type → Type) → Type) → ∀(x : HigherOrderType (λ(a : Type) → List a)) → HigherOrderType (λ(a : Type) → List a) dhall-1.19.1/tests/typecheck/success/simple/fieldsAreTypesA.dhall0000644000000000000000000000004113377175666023211 0ustar0000000000000000{ x = Bool, y = Text, z = List } dhall-1.19.1/tests/typecheck/success/simple/fieldsAreTypesB.dhall0000644000000000000000000000005213377175666023214 0ustar0000000000000000{ x : Type, y : Type, z : Type → Type } dhall-1.19.1/tests/typecheck/success/simple/kindParameterA.dhall0000644000000000000000000000010013377175666023050 0ustar0000000000000000λ(k : Kind) → λ(a : k → k → Type) → λ(x : k) → a x dhall-1.19.1/tests/typecheck/success/simple/kindParameterB.dhall0000644000000000000000000000007213377175666023061 0ustar0000000000000000∀(k : Kind) → (k → k → Type) → k → k → Type dhall-1.19.1/tests/typecheck/success/simple/mergeEquivalenceA.dhall0000644000000000000000000000023713377175666023556 0ustar0000000000000000 let Foo = < Bar : {} | Baz : {} > in λ(a : Type) → λ(f : {} → a) → λ(ts : Foo) → merge { Bar = λ(a : {}) → f a, Baz = f } ts dhall-1.19.1/tests/typecheck/success/simple/mergeEquivalenceB.dhall0000644000000000000000000000012013377175666023546 0ustar0000000000000000∀(a : Type) → ∀(f : {} → a) → ∀(ts : < Bar : {} | Baz : {} >) → a dhall-1.19.1/tests/typecheck/success/simple/mixedFieldAccessA.dhall0000644000000000000000000000043113377175666023465 0ustar0000000000000000-- 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-1.19.1/tests/typecheck/success/simple/mixedFieldAccessB.dhall0000644000000000000000000000003713377175666023470 0ustar0000000000000000< Private : {} | Public : {} > dhall-1.19.1/tests/typecheck/success/simple/access/0000755000000000000000000000000013377175666020425 5ustar0000000000000000dhall-1.19.1/tests/typecheck/success/simple/access/0A.dhall0000644000000000000000000000001713377175666021671 0ustar0000000000000000{ x = Text }.x dhall-1.19.1/tests/typecheck/success/simple/access/0B.dhall0000644000000000000000000000000513377175666021667 0ustar0000000000000000Type dhall-1.19.1/tests/typecheck/success/simple/access/1A.dhall0000644000000000000000000000004313377175666021671 0ustar0000000000000000< Foo : Text | Bar : Natural >.Foo dhall-1.19.1/tests/typecheck/success/simple/access/1B.dhall0000644000000000000000000000006313377175666021674 0ustar0000000000000000∀(Foo : Text) → < Bar : Natural | Foo : Text >