Safe Haskell | None |
---|---|
Language | Haskell98 |
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 reuse directory names as expressions. If you provide a path
to a local or remote directory then the compiler will look for a file named
@
within that directory and use that file to represent the directory.
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 a path 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"
- exprFromPath :: Path -> StateT Status IO (Expr Src Path)
- load :: Expr Src Path -> IO (Expr Src X)
- loadWith :: MonadCatch m => (Path -> StateT Status m (Expr Src Path)) -> Context (Expr Src X) -> Expr Src Path -> m (Expr Src X)
- loadWithContext :: Context (Expr Src X) -> Expr Src Path -> IO (Expr Src X)
- hashExpression :: Expr s X -> Digest SHA256
- hashExpressionToCode :: Expr s X -> Text
- data Status = Status {}
- emptyStatus :: Status
- newtype Cycle = Cycle {
- cyclicImport :: Path
- newtype ReferentiallyOpaque = ReferentiallyOpaque {
- opaqueImport :: Path
- data Imported e = Imported {
- importStack :: [Path]
- nested :: e
- newtype PrettyHttpException = PrettyHttpException HttpException
- data MissingFile = MissingFile FilePath
- newtype MissingEnvironmentVariable = MissingEnvironmentVariable {}
Import
exprFromPath :: Path -> StateT Status IO (Expr Src Path) Source #
Parse an expression from a Path
containing a Dhall program
loadWith :: MonadCatch m => (Path -> StateT Status m (Expr Src Path)) -> Context (Expr Src X) -> Expr Src Path -> m (Expr Src X) Source #
Resolve all imports within an expression using a custom typing context and Path
resolving callback in arbitrary MonadCatch
monad.
loadWithContext :: Context (Expr Src X) -> Expr Src Path -> IO (Expr Src X) Source #
Resolve all imports within an expression using a custom typing context.
load = loadWithContext Dhall.Context.empty
hashExpressionToCode :: 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
State threaded throughout the import process
Status | |
|
emptyStatus :: Status Source #
Default starting Status
An import failed because of a cycle in the import graph
Cycle | |
|
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
or127.0.0.1
All other imports are defined to be non-local
ReferentiallyOpaque | |
|
Extend another exception with the current import stack
Imported | |
|
newtype PrettyHttpException Source #
Newtype used to wrap HttpException
s with a prettier Show
instance
data MissingFile Source #
Exception thrown when an imported file is missing
newtype MissingEnvironmentVariable Source #
Exception thrown when an environment variable is missing