Dhall-lang: Normalizing `env:` imports

Created on 24 Jan 2019  Â·  5Comments  Â·  Source: dhall-lang/dhall-lang

I was writing an expression today (a simplified version):

{ api_key = env:API_KEY as Text }

When I went to freeze it, it froze the env: import, a la:

$ API_KEY=foo dhall freeze <<< '{ api_key = env:API_KEY as Text }'
{ api_key =
    env:API_KEY sha256:b2213295d564916f89a6a42455567c87c3f480fcd7a1c15e220f17d7169a790b as Text
}%

That freezes the value of foo. Looking at the semantics, that all seems right. Imports are resolved first, normalized, then frozen. In other words, I don't think there's any bug here.

My question is, what is the purpose of an env: import? Generally speaking, environment variables change. To some extent, they're expected to change. Is thinking about env: improts as we think about environment variables in other languages/tools/ecosystems (that they are knobs to change the behavior of a configuration/program) the wrong way to think about them in Dhall? Should there be another way to depend on environment variables akin to how we think of them in other languages/tools/ecosystems? I.e. something that doesn't require the normalization of env: imports? In my specific case, I converted to a function. But I'm wanting to understand the bigger picture.

Most helpful comment

Ok, some rough thoughts here, and after a bunch of waffling, I think I’ve landed somewhere in the middle, which (we all know) is where the right answers always are.

So,

  1. I think freezing is doing the right thing, but
  2. you don’t want to freeze your, uh, end-user(?) expressions.

An unfrozen env var is like a dynamically-scoped variable. It is a part of the interface of your expression that is hidden from the signature. Anywhere in your Dhall “libraries”, you should probably be using function parameters instead of env:. And freezing needs to freeze the definition of that expression, so it should freeze any env vars.

But, at the level of dhall expressions your users use/write, including env vars is very useful. Those expressions shouldn’t be frozen, and the env vars should work as expected.

But I think freezing does conflate a couple things – ultimately it’s freezing _that_ expression, which requires putting shas on _every_ import. But, there’s a weaker notion that looks like what you want here, where you don’t really want to freeze the expression, but you want to avoid unexpected changes to file imports. So you want to add shas to file imports, but not freeze the current expression (i.e., you don’t want to cache or close it off from the environment).

All 5 comments

Ok, some rough thoughts here, and after a bunch of waffling, I think I’ve landed somewhere in the middle, which (we all know) is where the right answers always are.

So,

  1. I think freezing is doing the right thing, but
  2. you don’t want to freeze your, uh, end-user(?) expressions.

An unfrozen env var is like a dynamically-scoped variable. It is a part of the interface of your expression that is hidden from the signature. Anywhere in your Dhall “libraries”, you should probably be using function parameters instead of env:. And freezing needs to freeze the definition of that expression, so it should freeze any env vars.

But, at the level of dhall expressions your users use/write, including env vars is very useful. Those expressions shouldn’t be frozen, and the env vars should work as expected.

But I think freezing does conflate a couple things – ultimately it’s freezing _that_ expression, which requires putting shas on _every_ import. But, there’s a weaker notion that looks like what you want here, where you don’t really want to freeze the expression, but you want to avoid unexpected changes to file imports. So you want to add shas to file imports, but not freeze the current expression (i.e., you don’t want to cache or close it off from the environment).

One way to view this is to use referential transparency to determine whether or not to freeze things. In other words, if an import is globally addressable (i.e. a remote import) then you freeze it because the meaning should not change based on the context. If an import is not globally addressable then you don't freeze it

Thinking about this more, another reason I think users probably don't want to freeze environment variables and local paths is that:

  • They are cheap to resolve (unlike remote imports), so they don't really benefit from caching

  • They are already trusted (by necessity) so they don't benefit from the security of the integrity check

    If the user did not trust their filesystem or environment variables then they can't trust the dhall interpreter they are running

Was this page helpful?
0 / 5 - 0 ratings

Related issues

RyanSiu1995 picture RyanSiu1995  Â·  3Comments

sjakobi picture sjakobi  Â·  5Comments

michalrus picture michalrus  Â·  5Comments

bwestergard picture bwestergard  Â·  4Comments

igrep picture igrep  Â·  3Comments