HORIZON HASKELLDocslts/ghc-9.10.xc74966e2026-09-27Search names, modules, packages, or :: a typeCtrl K

GHC 9.10.3 · lts/ghc-9.10.x · c74966e · 2026-09-27

Moduledhall-1.42.3Haskell2010

Dhall.Core

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

  • 24 types
  • 34 values
  • Packagedhall-1.42.3
  • Exports58
  • LanguageHaskell2010
  • LicenceBSD-3-Clause
  • SourceCore.hs

Syntax

24 declarations
datadata Const
#

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

Instances11Bounded, Enum, Eq, Data, Ord, Show, …
newtypenewtype Directory
#

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" ] }

Constructors

Instances10Eq, Data, Ord, Show, Generic, Semigroup, …
datadata File
#

A File is a directory followed by one additional path component representing the file name

Constructors

Instances10Eq, Data, Ord, Show, Generic, Semigroup, …
datadata FilePrefix
#

The beginning of a file path which anchors subsequent path components

Constructors

Instances8Eq, Data, Ord, Show, Generic, NFData, …
datadata Import
#

Reference to an external resource

Instances11Eq, Data, Ord, Show, Generic, Semigroup, …
datadata ImportHashed
#

A ImportType extended with an optional hash for semantic integrity checks

Instances10Eq, Data, Ord, Show, Generic, Semigroup, …
datadata ImportMode
#

How to interpret the import's contents (i.e. as Dhall code or raw text)

Instances7Eq, Data, Ord, Show, Generic, NFData, …
datadata ImportType
#

The type of import (i.e. local vs. remote vs. environment)

Constructors

Instances10Eq, Data, Ord, Show, Generic, Semigroup, …
datadata URL
#

This type stores all of the components of a remote import

Instances8Eq, Data, Ord, Show, Generic, NFData, …
datadata Scheme
#

The URI scheme

Instances7Eq, Data, Ord, Show, Generic, NFData, …
newtypenewtype DhallDouble
#

This wrapper around Double exists for its Eq instance which is defined via the binary encoding of Dhall Doubles.

Instances8Eq, Data, Ord, Show, Generic, NFData, …
  • Eq DhallDoubleDefined in dhall-1.42.3 · Dhall.Syntax.Instances.Eq · orphan

    This instance satisfies all the customary Eq laws except substitutivity.

    In particular:

    Example2 expressions
    nan = DhallDouble (0/0)nan == nanTrue

    This instance is also consistent with with the binary encoding of Dhall Doubles:

    Example1 expression
    toBytes n = Dhall.Binary.encodeExpression (DoubleLit n :: Expr Void Import)
    Property
    \a b -> (a == b) == (toBytes a == toBytes b)
  • Data DhallDoubleDefined in dhall-1.42.3 · Dhall.Syntax.Instances.Data · orphan
  • Ord DhallDoubleDefined in dhall-1.42.3 · Dhall.Syntax.Instances.Ord · orphan

    This instance relies on the Eq instance for DhallDouble but cannot satisfy the customary Ord laws when NaN is involved.

  • Show DhallDoubleDefined in dhall-1.42.3 · Dhall.Syntax.Instances.Show · orphan
  • Generic DhallDoubleDefined in dhall-1.42.3 · Dhall.Syntax.Types
  • NFData DhallDoubleDefined in dhall-1.42.3 · Dhall.Syntax.Instances.NFData · orphan
  • Lift DhallDoubleDefined in dhall-1.42.3 · Dhall.Syntax.Instances.Lift · orphan
  • type Rep DhallDouble = D1 ('MetaData "DhallDouble" "Dhall.Syntax.Types" "dhall-1.42.3-5OoAJpk2vIpARwiStLO8GU" 'True) (C1 ('MetaCons "DhallDouble" 'PrefixI 'True) (S1 ('MetaSel ('Just "getDhallDouble") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Double)))Defined in dhall-1.42.3 · Dhall.Syntax.Types
datadata Var
#

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 Vars and non-zero indices appear as a numeric suffix.

Constructors

Instances10Eq, Data, Ord, Show, IsString, Generic, …
datadata Binding s a
#

Record the binding part of a let expression.

For example,

let {- A -} x {- B -} : {- C -} Bool = {- D -} True in x

… will be instantiated as follows:

  • bindingSrc0 corresponds to the A comment.

  • variable is "x"

  • bindingSrc1 corresponds to the B comment.

  • annotation is Just a pair, corresponding to the C comment and Bool.

  • bindingSrc2 corresponds to the D comment.

  • value corresponds to True.

Instances12Bifunctor, Lift, Functor, Foldable, Traversable, Eq, …
datadata Chunks s a
#

The body of an interpolated Text literal

Constructors

Instances14Lift, Functor, Foldable, Traversable, Eq, Data, …
datadata PreferAnnotation
#

Used to record the origin of a // operator (i.e. from source code or a product of desugaring)

Instances8Eq, Data, Ord, Show, Generic, NFData, …
datadata RecordField s a
#

Record the field of a record-type and record-literal expression. The reason why we use the same ADT for both of them is because they store the same information.

For example,

{ {- A -} x {- B -} : {- C -} T }

... or

{ {- A -} x {- B -} = {- C -} T }

will be instantiated as follows:

  • recordFieldSrc0 corresponds to the A comment.

  • recordFieldValue is T

  • recordFieldSrc1 corresponds to the B comment.

  • recordFieldSrc2 corresponds to the C comment.

Although the A comment isn't annotating the T Record Field, this is the best place to keep these comments.

Note that recordFieldSrc2 is always Nothing when the RecordField is for a punned entry, because there is no = sign. For example,

{ {- A -} x {- B -} }

will be instantiated as follows:

  • recordFieldSrc0 corresponds to the A comment.

  • recordFieldValue corresponds to (Var "x")

  • recordFieldSrc1 corresponds to the B comment.

  • recordFieldSrc2 will be Nothing

The labels involved in a record using dot-syntax like in this example:

{ {- A -} a {- B -} . {- C -} b {- D -} . {- E -} c {- F -} = {- G -} e }

will be instantiated as follows:

  • For both the a and b field, recordfieldSrc2 is Nothing

  • For the a field:

  • recordFieldSrc0 corresponds to the A comment

  • recordFieldSrc1 corresponds to the B comment

  • For the b field:

  • recordFieldSrc0 corresponds to the C comment

  • recordFieldSrc1 corresponds to the D comment

  • For the c field:

  • recordFieldSrc0 corresponds to the E comment

  • recordFieldSrc1 corresponds to the F comment

  • recordFieldSrc2 corresponds to the G comment

That is, for every label except the last one the semantics of recordFieldSrc0 and recordFieldSrc1 are the same from a regular record label but recordFieldSrc2 is always Nothing. For the last keyword, all srcs are Just

Instances12Bifunctor, Lift, Functor, Foldable, Traversable, Eq, …
datadata FunctionBinding s a
#

Record the label of a function or a function-type expression

For example,

λ({- A -} a {- B -} : {- C -} T) -> e

… will be instantiated as follows:

  • functionBindingSrc0 corresponds to the A comment

  • functionBindingVariable is a

  • functionBindingSrc1 corresponds to the B comment

  • functionBindingSrc2 corresponds to the C comment

  • functionBindingAnnotation is T

Instances12Bifunctor, Lift, Functor, Foldable, Traversable, Eq, …
datadata FieldSelection s
#

Record the field on a selector-expression

For example,

e . {- A -} x {- B -}

… will be instantiated as follows:

  • fieldSelectionSrc0 corresponds to the A comment

  • fieldSelectionLabel corresponds to x

  • fieldSelectionSrc1 corresponds to the B comment

Given our limitation that not all expressions recover their whitespaces, the purpose of fieldSelectionSrc1 is to save the Text.Megaparsec.SourcePos where the fieldSelectionLabel ends, but we still use a 'Maybe Dhall.Src.Src' (s = Src) to be consistent with similar data types such as Binding, for example.

Instances11Functor, Foldable, Traversable, Lift, Eq, Data, …
datadata WithComponent
#

A path component for a with expression

Instances8Eq, Data, Ord, Show, Generic, NFData, …
datadata Expr s a
#

Syntax tree for expressions

The s type parameter is used to track the presence or absence of Src spans:

  • If s = Src then the code may contains Src spans (either in a Note constructor or inline within another constructor, like Let)

  • If s = Void then the code has no Src spans

The a type parameter is used to track the presence or absence of imports

Constructors

Instances18Bifunctor, Lift, Monad, Functor, Applicative, Foldable, …

Normalization

16 declarations
valuealphaNormalize :: Expr s a -> Expr s a
#

α-normalize an expression by renaming all bound variables to "_" and using De Bruijn indices to distinguish them

Example2 expressions
mfb = Syntax.makeFunctionBindingalphaNormalize (Lam mempty (mfb "a" (Const Type)) (Lam mempty (mfb "b" (Const Type)) (Lam mempty (mfb "x" "a") (Lam mempty (mfb "y" "b") "x"))))Lam Nothing (FunctionBinding {functionBindingSrc0 = Nothing, functionBindingVariable = "_", functionBindingSrc1 = Nothing, functionBindingSrc2 = Nothing, functionBindingAnnotation = Const Type}) (Lam Nothing (FunctionBinding {functionBindingSrc0 = Nothing, functionBindingVariable = "_", functionBindingSrc1 = Nothing, functionBindingSrc2 = Nothing, functionBindingAnnotation = Const Type}) (Lam Nothing (FunctionBinding {functionBindingSrc0 = Nothing, functionBindingVariable = "_", functionBindingSrc1 = Nothing, functionBindingSrc2 = Nothing, functionBindingAnnotation = Var (V "_" 1)}) (Lam Nothing (FunctionBinding {functionBindingSrc0 = Nothing, functionBindingVariable = "_", functionBindingSrc1 = Nothing, functionBindingSrc2 = Nothing, functionBindingAnnotation = Var (V "_" 1)}) (Var (V "_" 1)))))

α-normalization does not affect free variables:

Example1 expression
alphaNormalize "x"Var (V "x" 0)
valuenormalize :: Eq a => Expr s a -> Expr t 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.

normalize can also fail with error if you normalize an ill-typed expression

valuenormalizeWith :: Eq a => Maybe (ReifiedNormalizer a) -> Expr s a -> Expr t 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 can fail with an error if you normalize an ill-typed expression

valuesubst :: Var -> Expr s a -> Expr s a -> Expr s a
#

Substitute all occurrences of a variable with an expression

subst x C B  ~  B[x := C]
valueshift :: Int -> Var -> Expr s a -> Expr s a
#

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 xs 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.

valueisNormalized :: Eq a => Expr s a -> Bool
#

Quickly check if an expression is in normal form

Given a well-typed expression e, isNormalized e is equivalent to e == normalize e.

Given an ill-typed expression, isNormalized may fail with an error, or evaluate to either False or True!

valuedenote :: Expr s a -> Expr t a
#

Remove all Note constructors from an Expr (i.e. de-Note)

This also remove CharacterSet annotations.

valueshallowDenote :: Expr s a -> Expr s a
#

Remove any outermost Note constructors

This is typically used when you want to get the outermost non-Note constructor without removing internal Note constructors

valuefreeIn :: Eq a => Var -> Expr s a -> Bool
#

Detect if the given variable is free within the given expression

Example3 expressions
"x" `freeIn` "x"True"x" `freeIn` "y"False"x" `freeIn` Lam mempty (Syntax.makeFunctionBinding "x" (Const Type)) "x"False

Pretty-printing

1 declaration

Optics

6 declarations

Let-blocks

3 declarations

Miscellaneous

8 declarations
valueinternalError :: Text -> forall b. b
#

Utility function used to throw internal errors that should never happen (in theory) but that are not enforced by the type system

valueescapeText :: Text -> Text
#

Escape a Text literal using Dhall's escaping rules

Note that the result does not include surrounding quotes

valuecensorExpression :: Expr Src a -> Expr Src a
#

Utility used to implement the --censor flag, by:

  • Replacing all Src text with spaces

  • Replacing all Text literals inside type errors with spaces