dhall-1.41.2: A configuration language guaranteed to terminate

Safe Haskell | Safe-Inferred
Language | Haskell2010

Dhall.Import

Contents

- Import

Description

Dhall lets you import external expressions located either in local files or hosted on network endpoints.

To import a local file as an expression, just insert the path to the file, prepending a `./` if the path is relative to the current directory. For example, if you create a file named `id` with the following contents:

    $ cat id
    λ(a : Type) → λ(x : a) → x

Then you can use the file directly within a `dhall` program just by referencing the file's path:

    $ dhall
    ./id Bool True
    <Ctrl-D>
    Bool

    True

Imported expressions may contain imports of their own, too, which will continue to be resolved. However, Dhall will prevent cyclic imports. For example, if you had these two files:

    $ cat foo
    ./bar

    $ cat bar
    ./foo

... Dhall would throw the following exception if you tried to import `foo`:

    $ dhall
    ./foo
    ^D
    ↳ ./foo
      ↳ ./bar

    Cyclic import: ./foo

You can also import expressions hosted on network endpoints. Just use the URL

    http://host[:port]/path

The compiler expects the downloaded expressions to be in the same format as local files, specifically UTF8-encoded source code text.

For example, if our `id` expression were hosted at `http://example.com/id`, then we would embed the expression within our code using:

    http://example.com/id

You can also import expressions stored within environment variables using `env:NAME`, where `NAME` is the name of the environment variable. For example:

    $ export FOO=1
    $ export BAR='"Hi"'
    $ export BAZ='λ(x : Bool) → x == False'
    $ dhall <<< "{ foo = env:FOO , bar = env:BAR , baz = env:BAZ }"
    { bar : Text, baz : ∀(x : Bool) → Bool, foo : Integer }

    { bar = "Hi", baz = λ(x : Bool) → x == False, foo = 1 }

If you wish to import the raw contents of an impoert as `Text` then add `as Text` to the end of the import:

    $ dhall <<< "http://example.com as Text"
    Text

    "<!doctype html>\n<html>\n<head>\n    <title>Example Domain</title>\n\n    <meta
     charset=\"utf-8\" />\n    <meta http-equiv=\"Content-type\" content=\"text/html
    ; charset=utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-width,
    initial-scale=1\" />\n    <style type=\"text/css\">\n    body {\n        backgro
    und-color: #f0f0f2;\n        margin: 0;\n        padding: 0;\n        font-famil
    y: \"Open Sans\", \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n        \n
       }\n    div {\n        width: 600px;\n        margin: 5em auto;\n        paddi
    ng: 50px;\n        background-color: #fff;\n        border-radius: 1em;\n    }\n
        a:link, a:visited {\n        color: #38488f;\n        text-decoration: none;
    \n    }\n    @media (max-width: 700px) {\n        body {\n            background
    -color: #fff;\n        }\n        div {\n            width: auto;\n            m
    argin: 0 auto;\n            border-radius: 0;\n            padding: 1em;\n
      }\n    }\n    </style>    \n</head>\n\n<body>\n<div>\n    <h1>Example Domain</
    h1>\n    <p>This domain is established to be used for illustrative examples in d
    ocuments. You may use this\n    domain in examples without prior coordination or
     asking for permission.</p>\n    <p><a href=\"http://www.iana.org/domains/exampl
    e\">More information...</a></p>\n</div>\n</body>\n</html>\n"

Synopsis

- load :: Expr Src Import -> IO (Expr Src Void)
- loadWithManager :: IO Manager -> Expr Src Import -> IO (Expr Src Void)
- loadRelativeTo :: FilePath -> SemanticCacheMode -> Expr Src Import -> IO (Expr Src Void)
- loadWithStatus :: Status -> SemanticCacheMode -> Expr Src Import -> IO (Expr Src Void)
- loadWith :: Expr Src Import -> StateT Status IO (Expr Src Void)
- localToPath :: MonadIO io => FilePrefix -> File -> io FilePath
- hashExpression :: Expr Void Void -> SHA256Digest
- hashExpressionToCode :: Expr Void Void -> Text
- writeExpressionToSemanticCache :: Expr Void Void -> IO ()
- assertNoImports :: MonadIO io => Expr Src Import -> io (Expr Src Void)
- type Manager = Manager
- defaultNewManager :: IO Manager
- data CacheWarning
  - = CacheNotWarned
  - | CacheWarned
- data Status = Status {
  - _stack :: NonEmpty Chained
  - _graph :: [Depends]
  - _cache :: Map Chained ImportSemantics
  - _newManager :: IO Manager
  - _manager :: Maybe Manager
  - _loadOriginHeaders :: StateT Status IO OriginHeaders
  - _remote :: URL -> StateT Status IO Text
  - _substitutions :: Substitutions Src Void
  - _normalizer :: Maybe (ReifiedNormalizer Void)
  - _startingContext :: Context (Expr Src Void)
  - _semanticCacheMode :: SemanticCacheMode
  - _cacheWarning :: CacheWarning
  }
- data SemanticCacheMode
  - = IgnoreSemanticCache
  - | UseSemanticCache
- data Chained
- chainedImport :: Chained -> Import
- chainedFromLocalHere :: FilePrefix -> File -> ImportMode -> Chained
- chainedChangeMode :: ImportMode -> Chained -> Chained
- emptyStatus :: FilePath -> Status
- emptyStatusWithManager :: IO Manager -> FilePath -> Status
- envOriginHeaders :: Expr Src Import
- makeEmptyStatus :: IO Manager -> IO (Expr Src Import) -> FilePath -> Status
- remoteStatus :: URL -> Status
- remoteStatusWithManager :: IO Manager -> URL -> Status
- fetchRemote :: URL -> StateT Status IO Text
- stack :: Functor f => LensLike' f Status (NonEmpty Chained)
- cache :: Functor f => LensLike' f Status (Map Chained ImportSemantics)
- data Depends = Depends {
  - parent :: Chained
  - child :: Chained
  }
- graph :: Functor f => LensLike' f Status [Depends]
- remote :: Functor f => LensLike' f Status (URL -> StateT Status IO Text)
- toHeaders :: Expr s a -> [HTTPHeader]
- substitutions :: Functor f => LensLike' f Status (Substitutions Src Void)
- normalizer :: Functor f => LensLike' f Status (Maybe (ReifiedNormalizer Void))
- startingContext :: Functor f => LensLike' f Status (Context (Expr Src Void))
- chainImport :: Chained -> Import -> StateT Status IO Chained
- dependencyToFile :: Status -> Import -> IO (Maybe FilePath)
- data ImportSemantics
- type HTTPHeader = (CI ByteString, ByteString)
- newtype Cycle = Cycle {
  - cyclicImport :: Import
  }
- newtype ReferentiallyOpaque = ReferentiallyOpaque {
  - opaqueImport :: Import
  }
- data Imported e = Imported {
  - importStack :: NonEmpty Chained
  - nested :: e
  }
- data ImportResolutionDisabled = ImportResolutionDisabled
- data PrettyHttpException = PrettyHttpException String Dynamic
- newtype MissingFile = MissingFile FilePath
- newtype MissingEnvironmentVariable = MissingEnvironmentVariable {
  - name :: Text
  }
- newtype MissingImports = MissingImports [SomeException]
- data HashMismatch = HashMismatch {
  - expectedHash :: SHA256Digest
  - actualHash :: SHA256Digest
  }

# Import

load :: Expr Src Import -> IO (Expr Src Void) Source #

Resolve all imports within an expression

loadWithManager :: IO Manager -> Expr Src Import -> IO (Expr Src Void) Source #

See `load`.

loadRelativeTo :: FilePath -> SemanticCacheMode -> Expr Src Import -> IO (Expr Src Void) Source #

Resolve all imports within an expression, importing relative to the given directory.

loadWithStatus :: Status -> SemanticCacheMode -> Expr Src Import -> IO (Expr Src Void) Source #

See `loadRelativeTo`.

loadWith :: Expr Src Import -> StateT Status IO (Expr Src Void) Source #

Generalized version of `load`

You can configure the desired behavior through the initial `Status` that you supply

localToPath :: MonadIO io => FilePrefix -> File -> io FilePath Source #

Construct the file path corresponding to a local import. If the import is _relative_ then the resulting path is also relative.

hashExpression :: Expr Void Void -> SHA256Digest Source #

Hash a fully resolved expression

hashExpressionToCode :: Expr Void Void -> Text Source #

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

writeExpressionToSemanticCache :: Expr Void Void -> IO () Source #

Ensure that the given expression is present in the semantic cache. The given expression should be alpha-beta-normal.

assertNoImports :: MonadIO io => Expr Src Import -> io (Expr Src Void) Source #

Assert than an expression is import-free

type Manager = Manager Source #

Shared state for HTTP requests

defaultNewManager :: IO Manager Source #

The default HTTP `Manager`

data CacheWarning Source #

Used internally to track whether or not we've already warned the user about caching issues

Constructors

CacheNotWarned |
CacheWarned |

data Status Source #

State threaded throughout the import process

Constructors

Status |

Fields

- _stack :: NonEmpty Chained

  Stack of `Import`s that we've imported along the way to get to the current point

- _graph :: [Depends]

  Graph of all the imports visited so far, represented by a list of import dependencies.

- _cache :: Map Chained ImportSemantics

  Cache of imported expressions with their node id in order to avoid importing the same expression twice with different values

- _newManager :: IO Manager
- _manager :: Maybe Manager

  Used to cache the `Manager` when making multiple requests

- _loadOriginHeaders :: StateT Status IO OriginHeaders

  Load the origin headers from environment or configuration file. After loading once, further evaluations return the cached version.

- _remote :: URL -> StateT Status IO Text

  The remote resolver, fetches the content at the given URL.

- _substitutions :: Substitutions Src Void
- _normalizer :: Maybe (ReifiedNormalizer Void)
- _startingContext :: Context (Expr Src Void)
- _semanticCacheMode :: SemanticCacheMode
- _cacheWarning :: CacheWarning

  Records whether or not we already warned the user about issues with cache directory

data SemanticCacheMode Source #

This enables or disables the semantic cache for imports protected by integrity checks

Constructors

IgnoreSemanticCache |
UseSemanticCache |

#### Instances

Instances details

Eq SemanticCacheMode Source # |
Instance details Defined in Dhall.Import.Types Methods (==) :: SemanticCacheMode -> SemanticCacheMode -> Bool Source # (/=) :: SemanticCacheMode -> SemanticCacheMode -> Bool Source #

data Chained Source #

A fully "chained" import, i.e. if it contains a relative path that path is relative to the current directory. If it is a remote import with headers those are well-typed (either of type `List { header : Text, value Text}` or `List { mapKey : Text, mapValue Text})` and in normal form. These invariants are preserved by the API exposed by `Dhall.Import`.

#### Instances

Instances details

Eq Chained Source # |
Instance details Defined in Dhall.Import.Types Methods (==) :: Chained -> Chained -> Bool Source # (/=) :: Chained -> Chained -> Bool Source #
Ord Chained Source # |
Instance details Defined in Dhall.Import.Types Methods compare :: Chained -> Chained -> Ordering Source # (<) :: Chained -> Chained -> Bool Source # (<=) :: Chained -> Chained -> Bool Source # (>) :: Chained -> Chained -> Bool Source # (>=) :: Chained -> Chained -> Bool Source # max :: Chained -> Chained -> Chained Source # min :: Chained -> Chained -> Chained Source #
Pretty Chained Source # |
Instance details Defined in Dhall.Import.Types Methods pretty :: Chained -> Doc ann Source # prettyList :: [Chained] -> Doc ann Source #

chainedImport :: Chained -> Import Source #

The underlying import

chainedFromLocalHere :: FilePrefix -> File -> ImportMode -> Chained Source #

Given a `Local` import construct the corresponding unhashed `Chained` import (interpreting relative path as relative to the current directory).

chainedChangeMode :: ImportMode -> Chained -> Chained Source #

Adjust the import mode of a chained import

emptyStatus :: FilePath -> Status Source #

Default starting `Status`, importing relative to the given directory.

emptyStatusWithManager :: IO Manager -> FilePath -> Status Source #

See `emptyStatus`

envOriginHeaders :: Expr Src Import Source #

Load headers only from the environment (used in tests)

makeEmptyStatus :: IO Manager -> IO (Expr Src Import) -> FilePath -> Status Source #

See `emptyStatus`.

remoteStatus Source #

Arguments

:: URL | Public address of the server
-> Status |

Default `Status` appropriate for a server interpreting Dhall code

Using this `Status` ensures that interpreted Dhall code cannot access server-local resources (like files or environment variables)

remoteStatusWithManager :: IO Manager -> URL -> Status Source #

See `remoteStatus`

fetchRemote :: URL -> StateT Status IO Text Source #

Fetch the text contents of a URL

stack :: Functor f => LensLike' f Status (NonEmpty Chained) Source #

Lens from a `Status` to its `_stack` field

cache :: Functor f => LensLike' f Status (Map Chained ImportSemantics) Source #

Lens from a `Status` to its `_cache` field

data Depends Source #

`parent` imports (i.e. depends on) `child`

Constructors

Depends |

Fields

- parent :: Chained
- child :: Chained

graph :: Functor f => LensLike' f Status [Depends] Source #

Lens from a `Status` to its `_graph` field

remote :: Functor f => LensLike' f Status (URL -> StateT Status IO Text) Source #

Lens from a `Status` to its `_remote` field

toHeaders :: Expr s a -> [HTTPHeader] Source #

Given a well-typed (of type `List { header : Text, value Text }` or `List { mapKey : Text, mapValue Text }`) headers expressions in normal form construct the corresponding binary http headers; otherwise return the empty list.

substitutions :: Functor f => LensLike' f Status (Substitutions Src Void) Source #

Lens from a `Status` to its `_substitutions` field

normalizer :: Functor f => LensLike' f Status (Maybe (ReifiedNormalizer Void)) Source #

Lens from a `Status` to its `_normalizer` field

startingContext :: Functor f => LensLike' f Status (Context (Expr Src Void)) Source #

Lens from a `Status` to its `_startingContext` field

chainImport :: Chained -> Import -> StateT Status IO Chained Source #

Chain imports, also typecheck and normalize headers if applicable.

dependencyToFile :: Status -> Import -> IO (Maybe FilePath) Source #

This function is used by the `--transitive` option of the `dhall {freeze,format,lint}` subcommands to determine which dependencies to descend into

    >>> dependencyToFile (emptyStatus ".") Import{ importHashed = ImportHashed{ hash = Nothing, importType = Local Here (File (Directory []) "foo") }, importMode = Code }
    Just "./foo"

    >>> dependencyToFile (emptyStatus "./foo") Import{ importHashed = ImportHashed{ hash = Nothing, importType = Local Here (File (Directory []) "bar") }, importMode = Code }
    Just "./foo/bar"

    >>> dependencyToFile (emptyStatus "./foo") Import{ importHashed = ImportHashed{ hash = Nothing, importType = Remote (URL HTTPS "example.com" (File (Directory []) "") Nothing Nothing) }, importMode = Code }
    Nothing

    >>> dependencyToFile (emptyStatus ".") Import{ importHashed = ImportHashed{ hash = Nothing, importType = Env "foo" }, importMode = Code }
    Nothing

data ImportSemantics Source #

An import that has been fully interpeted

type HTTPHeader = (CI ByteString, ByteString) Source #

HTTP headers

newtype Cycle Source #

An import failed because of a cycle in the import graph

Constructors

Cycle |

Fields

- cyclicImport :: Import

  The offending cyclic import

#### Instances

Instances details

Exception Cycle Source # |
Instance details Defined in Dhall.Import Methods toException :: Cycle -> SomeException Source # fromException :: SomeException -> Maybe Cycle Source # displayException :: Cycle -> String Source #
Show Cycle Source # |
Instance details Defined in Dhall.Import Methods showsPrec :: Int -> Cycle -> ShowS Source # show :: Cycle -> String Source # showList :: [Cycle] -> ShowS Source #

newtype ReferentiallyOpaque Source #

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

Constructors

ReferentiallyOpaque |

Fields

- opaqueImport :: Import

  The offending opaque import

#### Instances

Instances details

Exception ReferentiallyOpaque Source # |
Instance details Defined in Dhall.Import Methods toException :: ReferentiallyOpaque -> SomeException Source # fromException :: SomeException -> Maybe ReferentiallyOpaque Source # displayException :: ReferentiallyOpaque -> String Source #
Show ReferentiallyOpaque Source # |
Instance details Defined in Dhall.Import Methods showsPrec :: Int -> ReferentiallyOpaque -> ShowS Source # show :: ReferentiallyOpaque -> String Source # showList :: [ReferentiallyOpaque] -> ShowS Source #

data Imported e Source #

Extend another exception with the current import stack

Constructors

Imported |

Fields

- importStack :: NonEmpty Chained

  Imports resolved so far, in reverse order

- nested :: e

  The nested exception

#### Instances

Instances details

Exception e => Exception (Imported e) Source # |
Instance details Defined in Dhall.Import Methods toException :: Imported e -> SomeException Source # fromException :: SomeException -> Maybe (Imported e) Source # displayException :: Imported e -> String Source #
Show e => Show (Imported e) Source # |
Instance details Defined in Dhall.Import Methods showsPrec :: Int -> Imported e -> ShowS Source # show :: Imported e -> String Source # showList :: [Imported e] -> ShowS Source #

data ImportResolutionDisabled Source #

A call to `assertNoImports` failed because there was at least one import

Constructors

ImportResolutionDisabled |

#### Instances

Instances details

Exception ImportResolutionDisabled Source # |
Instance details Defined in Dhall.Import Methods toException :: ImportResolutionDisabled -> SomeException Source # fromException :: SomeException -> Maybe ImportResolutionDisabled Source # displayException :: ImportResolutionDisabled -> String Source #
Show ImportResolutionDisabled Source # |
Instance details Defined in Dhall.Import Methods showsPrec :: Int -> ImportResolutionDisabled -> ShowS Source # show :: ImportResolutionDisabled -> String Source # showList :: [ImportResolutionDisabled] -> ShowS Source #

data PrettyHttpException Source #

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 `HttpException` is stored in a `Dynamic`

Constructors

PrettyHttpException String Dynamic |

#### Instances

Instances details

Exception PrettyHttpException Source # |
Instance details Defined in Dhall.Import.Types Methods toException :: PrettyHttpException -> SomeException Source # fromException :: SomeException -> Maybe PrettyHttpException Source # displayException :: PrettyHttpException -> String Source #
Show PrettyHttpException Source # |
Instance details Defined in Dhall.Import.Types Methods showsPrec :: Int -> PrettyHttpException -> ShowS Source # show :: PrettyHttpException -> String Source # showList :: [PrettyHttpException] -> ShowS Source #

newtype MissingFile Source #

Exception thrown when an imported file is missing

Constructors

MissingFile FilePath |

#### Instances

Instances details

Exception MissingFile Source # |
Instance details Defined in Dhall.Import Methods toException :: MissingFile -> SomeException Source # fromException :: SomeException -> Maybe MissingFile Source # displayException :: MissingFile -> String Source #
Show MissingFile Source # |
Instance details Defined in Dhall.Import Methods showsPrec :: Int -> MissingFile -> ShowS Source # show :: MissingFile -> String Source # showList :: [MissingFile] -> ShowS Source #

newtype MissingEnvironmentVariable Source #

Exception thrown when an environment variable is missing

Constructors

MissingEnvironmentVariable |

Fields

- name :: Text

#### Instances

Instances details

Exception MissingEnvironmentVariable Source # |
Instance details Defined in Dhall.Import Methods toException :: MissingEnvironmentVariable -> SomeException Source # fromException :: SomeException -> Maybe MissingEnvironmentVariable Source # displayException :: MissingEnvironmentVariable -> String Source #
Show MissingEnvironmentVariable Source # |
Instance details Defined in Dhall.Import Methods showsPrec :: Int -> MissingEnvironmentVariable -> ShowS Source # show :: MissingEnvironmentVariable -> String Source # showList :: [MissingEnvironmentVariable] -> ShowS Source #

newtype MissingImports Source #

List of Exceptions we encounter while resolving Import Alternatives

Constructors

MissingImports [SomeException] |

#### Instances

Instances details

Exception MissingImports Source # |
Instance details Defined in Dhall.Import Methods toException :: MissingImports -> SomeException Source # fromException :: SomeException -> Maybe MissingImports Source # displayException :: MissingImports -> String Source #
Show MissingImports Source # |
Instance details Defined in Dhall.Import Methods showsPrec :: Int -> MissingImports -> ShowS Source # show :: MissingImports -> String Source # showList :: [MissingImports] -> ShowS Source #

data HashMismatch Source #

Exception thrown when an integrity check fails

Constructors

HashMismatch |

Fields

- expectedHash :: SHA256Digest
- actualHash :: SHA256Digest

#### Instances

Instances details

Exception HashMismatch Source # |
Instance details Defined in Dhall.Import Methods toException :: HashMismatch -> SomeException Source # fromException :: SomeException -> Maybe HashMismatch Source # displayException :: HashMismatch -> String Source #
Show HashMismatch Source # |
Instance details Defined in Dhall.Import Methods showsPrec :: Int -> HashMismatch -> ShowS Source # show :: HashMismatch -> String Source # showList :: [HashMismatch] -> ShowS Source #