Comments (13)
Originally I intended to extend the ∧
operator to behave the way you ask (i.e. if there is a conflict between two fields that are not both records then prefer the right field).
The problem is when you have expressions like this:
λ(x : Text) → λ(y : {}) → { foo = x } ∧ { bar = y }
What would you expect that to normalize to?
from dhall-lang.
Oops, I meant to say:
λ(x : Text) → λ(y : {}) → { foo = x } ∧ { foo = y }
from dhall-lang.
In this case I would expect { foo = {} }
as a result.
My reasoning would be intuitive and "imperative":
foo
is set tox
.combine
happens and we check conflicting fields: "if both fields are records then combine them, otherwise RHS wins". Sincefoo
is set tox: Text
now,combine
prefers RHS value.
from dhall-lang.
The issue with that is that it would require interleaving type-checking with normalization which would significantly complicate the semantics. We would need to know that x
has type Text
and y
has type {}
in order to know that they conflict and y
takes precedence. Also, in general I try to avoid users having to reason at the type level in order to infer what is happening at the term level.
Another issue with a recursive override operator is that it is no longer associative. For example:
x = { foo = { bar = 1 } }
y = { foo = "ABC" }
z = { foo = { baz = 2 } }
(x ∧ y) ∧ z = { foo = { baz = 2 } }
x ∧ (y ∧ z) = { foo = { baz = 1, baz = 2 } }
from dhall-lang.
Hm, OK, I thought it would be just a check whether both fields are records are not, which would need to be done anyway to determine whether to go deeper.
I am fine with non-associativity here. But I understand why it is a concern and this is why I am not asking to change the existing behaviour but rather to introduce another variation of combine
.
It would allow pretty common use case for dealing with "big" APIs and configuration, like dealing Singularity where asking users to specify every single property of these types is impractical.
from dhall-lang.
The reason you require type inference is because some fields might be bound variables, so you can't tell if the bound variable is a record or not without knowing its type
I also think the lack of associativity is an important reason why I wouldn't want to introduce this operator (even as a new operator). One of the design principles of Dhall is that all operators should be associative
Also, note that you can still update a nested record without specifying every field. In the worst case you can use the ⫽
operator once per nesting level, like this:
let example = { foo = { bar = { baz = 1 } } }
in example ⫽ { foo = example.foo ⫽ { bar = example.foo.bar ⫽ { baz = 2 } } }
It's not ideal, but it at least doesn't require specifying the other fields at each nesting level
from dhall-lang.
Yeah, I think I'll have to go this way then, will see how it goes.
Thanks for the explanation.
from dhall-lang.
You're welcome!
from dhall-lang.
I will go ahead and close this, but feel free to reopen if there is more to do here.
from dhall-lang.
I'd just like to add that I always wanted the requested behavior in Nix and I'm sad to see dhall doesn't do it right, even though I understand it goes outside of desired design space.
A quite common configuration pattern is default values. One file has the defaults, the other overrides them for example like ./defaults.dhall /\ { ... }
Currently one can use //
if the configuration is nested using Gabriel's trick, but can't use /\
as defaults can't be used.
Having a good story for defaults is important for introducing new fields to the configuration as the application using them gets new settings through it's lifetime.
from dhall-lang.
@domenkozar: My main issue with the requested behavior is that it requires interleaving type-checking and normalization. Not only does this complicate the standard but it also complicates the user's mental model since they can't reason about how ∧
behaves without performing type inference in their head.
However, even if we were to accept that tradeoff, it still wouldn't completely solve the problem. For example, consider the case where you have a configuration of type:
{ foo : Optional Text, bar : List { baz : Optional Text } }
The ∧
wouldn't be able to recurse into the record inside the List
of the bar
field.
For a non-contrived example of this, see the menucolors.*.attributes
field of the dhall-nethack
configuration:
from dhall-lang.
Reopening this as we've been discussing adding a with
keyword for deep overrides here: #754 (comment)
from dhall-lang.
The fix for this is up here: #923
from dhall-lang.
Related Issues (20)
- `with` record update syntax removes other record fields HOT 4
- ABNF grammar should list "as Bytes" import mode
- Should the ABNF grammar disallow shebangs inside expressions? HOT 1
- eta-reducing to merge HOT 4
- Builtins operators reference: Missing record projection HOT 2
- ABNF grammar should explicitly disallow keywords as identifiers? HOT 2
- ABNF grammar should include a mandatory whitespace after `import-hashed`? HOT 1
- Improvements and fixes in the standard documentation HOT 3
- Is this an incorrect test file: `dhall-lang/tests/import/success/unit/ImportRelativeToHomeB.dhall`? HOT 2
- Link to non existing tweet
- A minimalistic proposal for do-notation
- Thoughts on introducing a minimum amount of type inference in Dhall HOT 1
- Introduce Bytes/length and Text/length as built-ins? HOT 3
- Is there a security hole: malicious sha256-protected cached content? HOT 1
- Eta-equivalence in `assert`? HOT 13
- A type level equivalent of the `with` keyword HOT 11
- Convert assertions to Leibniz equality types HOT 3
- A minimalistic proposal for adding row and column polymorphism to Dhall HOT 2
- A proposal for a "lightweight Dhall implementations" standard
- Year, Month, and Date extraction from a Date HOT 6
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from dhall-lang.