dhall-1.19.1: A configuration language guaranteed to terminate

Safe Haskell | None
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

- exprFromImport :: Import -> StateT (Status IO) IO (Expr Src Import)
- exprToImport :: Import -> Expr Src X -> StateT (Status IO) IO ()
- load :: Expr Src Import -> IO (Expr Src X)
- loadWith :: MonadCatch m => Expr Src Import -> StateT (Status m) m (Expr Src X)
- hashExpression :: StandardVersion -> Expr s X -> Digest SHA256
- hashExpressionToCode :: StandardVersion -> Expr s X -> Text
- assertNoImports :: MonadIO io => Expr Src Import -> io (Expr Src X)
- data Status m
- emptyStatus :: FilePath -> Status IO
- stack :: Functor f => LensLike' f (Status m) (NonEmpty Import)
- cache :: Functor f => LensLike' f (Status m) (Map Import (NodeId, Expr Src X))
- manager :: Functor f => LensLike' f (Status m) (Maybe Dynamic)
- standardVersion :: Functor f => LensLike' f (Status m) StandardVersion
- normalizer :: Functor f => LensLike' f (Status m) (ReifiedNormalizer X)
- startingContext :: Functor f => LensLike' f (Status m) (Context (Expr Src X))
- resolver :: Functor f => LensLike' f (Status m) (Import -> StateT (Status m) m (Expr Src Import))
- cacher :: Functor f => LensLike' f (Status m) (Import -> Expr Src X -> StateT (Status m) m ())
- newtype Cycle = Cycle {
  - cyclicImport :: Import
  }
- newtype ReferentiallyOpaque = ReferentiallyOpaque {
  - opaqueImport :: Import
  }
- data Imported e = Imported {
  - importStack :: NonEmpty Import
  - nested :: e
  }
- data ImportResolutionDisabled = ImportResolutionDisabled
- data PrettyHttpException = PrettyHttpException String Dynamic
- data MissingFile = MissingFile FilePath
- newtype MissingEnvironmentVariable = MissingEnvironmentVariable {
  - name :: Text
  }
- newtype MissingImports = MissingImports [SomeException]

# Import

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

Parse an expression from a `Import` containing a Dhall program

exprToImport :: Import -> Expr Src X -> StateT (Status IO) IO () Source #

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)

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

Resolve all imports within an expression

loadWith :: MonadCatch m => Expr Src Import -> StateT (Status m) m (Expr Src X) Source #

Generalized version of `load`

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

hashExpression :: StandardVersion -> Expr s X -> Digest SHA256 Source #

Hash a fully resolved expression

hashExpressionToCode :: StandardVersion -> Expr s X -> 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

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

Assert than an expression is import-free

data Status m Source #

State threaded throughout the import process

emptyStatus :: FilePath -> Status IO Source #

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

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

cache :: Functor f => LensLike' f (Status m) (Map Import (NodeId, Expr Src X)) Source #

manager :: Functor f => LensLike' f (Status m) (Maybe Dynamic) Source #

standardVersion :: Functor f => LensLike' f (Status m) StandardVersion Source #

normalizer :: Functor f => LensLike' f (Status m) (ReifiedNormalizer X) Source #

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

resolver :: Functor f => LensLike' f (Status m) (Import -> StateT (Status m) m (Expr Src Import)) Source #

cacher :: Functor f => LensLike' f (Status m) (Import -> Expr Src X -> StateT (Status m) m ()) Source #

newtype Cycle Source #

An import failed because of a cycle in the import graph

Constructors

Cycle |

Fields

- cyclicImport :: Import

  The offending cyclic import

Instances

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

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

data Imported e Source #

Extend another exception with the current import stack

Constructors

Imported |

Fields

- importStack :: NonEmpty Import

  Imports resolved so far, in reverse order

- nested :: e

  The nested exception

Instances

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 #
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 #

data ImportResolutionDisabled Source #

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

Constructors

ImportResolutionDisabled |

Instances

Show ImportResolutionDisabled Source # |
Instance details Defined in Dhall.Import Methods showsPrec :: Int -> ImportResolutionDisabled -> ShowS Source # show :: ImportResolutionDisabled -> String Source # showList :: [ImportResolutionDisabled] -> ShowS Source #
Exception ImportResolutionDisabled Source # |
Instance details Defined in Dhall.Import Methods toException :: ImportResolutionDisabled -> SomeException Source # fromException :: SomeException -> Maybe ImportResolutionDisabled Source # displayException :: ImportResolutionDisabled -> String 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 `HttpExcepion` is stored in a `Dynamic`

Constructors

PrettyHttpException String Dynamic |

Instances

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

data MissingFile Source #

Exception thrown when an imported file is missing

Constructors

MissingFile FilePath |

Instances

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

newtype MissingEnvironmentVariable Source #

Exception thrown when an environment variable is missing

Constructors

MissingEnvironmentVariable |

Fields

- name :: Text

Instances

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

newtype MissingImports Source #

List of Exceptions we encounter while resolving Import Alternatives

Constructors

MissingImports [SomeException] |

Instances

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