-
Notifications
You must be signed in to change notification settings - Fork 217
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement "Generalize empty list annotations" #1112
Conversation
dhall/src/Dhall/Binary.hs
Outdated
_T₁ = case _T₀ of | ||
Nothing -> TNull | ||
Just t -> encode t | ||
(label, _T₁) = case fmap Dhall.Core.denote _T₀ of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
denote
was required to get the parser tests to pass. I suspect the denoting should happen in the test setup though.
Usually we can assume that the expressions we encode here are already denoted, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can enforce that in the types by changing the first type parameter of Expr
to X
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean changing the instance head to
instance ToTerm a => ToTerm (Expr X a)
?
I tried to do this and followed the type errors for a bit. Eventually there's some code in Dhall.Import
that currently relies on an instance for Expr Src X
. Maybe I'll revisit that idea later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I realize now that the denot
ing here is only necessary because I stopped shallowDenot
ing the type in Dhall.Parser.Expression
. I think the parser change was a good idea as we now have a more fully annotated parse tree.
Is it ok if I leave this code like it is now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we still want to change the ToTerm
instance, we should do that separately, as that will be a good-sized change by itself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you should either (A) denote
the entire syntax tree once before decoding, rather than doing a denote
here or (B) do a shallowDenote
here. The main thing that I want to prevent is the inefficiency of multiple recursive denote
s
Personally, I think (A) is simpler
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(A) would mean that an already denoted Expr would get denoted again when we encode it. I'd rather change the instance head from Expr s a
to Expr X a
.
But that might cause some churn elsewhere – so I'm not too keen on it.
I think the denote
here is ok: denote
is very lazy, so it will only denote the List
and the App
, and be done.
If you disagree, I'd move shallowDenote
into Dhall.Core
and re-use it here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In that case I think we should go with shallowDenote
Even though denote
is lazy, if you have nested lists they will build up (i.e. the Nth nested list would have to step through N separate denote
functions for each node in the abstract syntax tree). I know that this is unlikely to be an issue in practice, but it can't hurt to fix
@@ -424,7 +424,7 @@ data Expr s a | |||
| TextShow | |||
-- | > List ~ List | |||
| List | |||
-- | > ListLit (Just t ) [x, y, z] ~ [x, y, z] : List t | |||
-- | > ListLit (Just t ) [x, y, z] ~ [x, y, z] : t |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These docs are a bit misleading: In the parser, we only insert the type into the ListLit
when we have an empty list literal. I'm wondering why though!
Should there be an invariant that we have a Just t
iff the list is empty?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, there should be such an invariant
The more accurate way to encode things in the types would be to have separate Expr
constructors for empty lists and non-empty lists, like:
| EmptyListLit (Expr s a)
| NonEmptyListLit (NonEmptySeq (Expr s a))
... but that would be a more disruptive change
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, another way you could do this is to remove the type annotation entirely from the List
constructor. In other words:
ListLit (Seq (Expr s a))
... and instead the type-checker can enforce that empty list literals are of the form Annot (ListList []) a
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think having a separate constructor for empty lists is much clearer. Should I open an issue to discuss the idea before I attempt implementing it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sjakobi: The main reason I suggest using Annot
is because it's closer to the standard (since now an empty list without an annotation is a type error rather than a syntax error)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(since now an empty list without an annotation is a type error rather than a syntax error)
Do you suggest deviating from the standard here @Gabriel439?
Currently we still have tests/parser/failure/unit/ListLitEmptyAnnotation
and the rule "[" whsp "]" whsp ":" whsp1 annotation-expression
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, you're right, it is still part of the grammar. I still think splitting out the empty list constructor would be a bit disruptive, though.
@@ -424,7 +424,7 @@ data Expr s a | |||
| TextShow | |||
-- | > List ~ List | |||
| List | |||
-- | > ListLit (Just t ) [x, y, z] ~ [x, y, z] : List t | |||
-- | > ListLit (Just t ) [x, y, z] ~ [x, y, z] : t |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, there should be such an invariant
The more accurate way to encode things in the types would be to have separate Expr
constructors for empty lists and non-empty lists, like:
| EmptyListLit (Expr s a)
| NonEmptyListLit (NonEmptySeq (Expr s a))
... but that would be a more disruptive change
@@ -424,7 +424,7 @@ data Expr s a | |||
| TextShow | |||
-- | > List ~ List | |||
| List | |||
-- | > ListLit (Just t ) [x, y, z] ~ [x, y, z] : List t | |||
-- | > ListLit (Just t ) [x, y, z] ~ [x, y, z] : t |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, another way you could do this is to remove the type annotation entirely from the List
constructor. In other words:
ListLit (Seq (Expr s a))
... and instead the type-checker can enforce that empty list literals are of the form Annot (ListList []) a
The tests rely both on dhall-lang/dhall-lang#644 and dhall-lang/dhall-lang#641. I'll update the submodule once at least one of them has been merged. |
9d60c34
to
ed6e334
Compare
ed6e334
to
b8ba141
Compare
Oops. I forgot to switch to |
…as standardized in dhall-lang/dhall-lang#630 Also: * Update the dhall-lang submodule to the state of dhall-lang/dhall-lang#654. * Skip the nonCharacter test for now. Fixes #414. Fixes #770.
b8ba141
to
66ddc4a
Compare
…as standardized in dhall-lang/dhall-lang#630
Fixes #414.
Fixes #770.