-
Notifications
You must be signed in to change notification settings - Fork 214
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
Add a new environment machine normalizer #876
Conversation
Old GHCs trip up on |
@AndrasKovacs First of all congrats for this awesome improvement to dhall-haskell Re Strict: I am afraid that remove the pragma would need a important change in the modules cause you should add explicit strict annotations everywhere (following the semantics of the pragma: https://gitlab.haskell.org/ghc/ghc/wikis/strict-pragma#strict) |
@jneira adding strictness annotations is no big deal. On the other hand, adapting the codebase to the new normalizer is a substantial change, and ideally I'd like to defer that work to a new branch on |
@AndrasKovacs: Sorry for the delay; I was a bit sick recently. The reason CI builds against GHC 7.10.3 is to support Etlas (the package manager for Eta). Eta/Etlas are built with GHC 7.10.3 and Etlas depends on Dhall (since Dhall is an officially supported configuration format for configuring Etlas packages). So we have to figure out some way to merge this will supporting GHC 7.10.3. I can think of two main solutions:
My weak preference is for the latter solution, since it seems like the other changes in this pull request are responsible for the large performance gains. |
@AndrasKovacs: Instead of adding a I was actually going to suggest going a step further and replacing |
Thanks for the feedback! I'll remove the If that works, it's OK for now, but that's still overall very inefficient with the current typechecker and import resolver. I plan to switch them as well to the standard NbE algorithm, and I think I can do this sometime in the next 2 weeks. |
@AndrasKovacs: Yeah, I'm fine merging this even with just the improvement to normalization performance. From my point of view the main reason to merge this is to reduce your maintenance burden since once you merge this into |
- Dhall.Eval: new evaluator, conversion checker and normalizer. There is no standalone alpha normalizer yet. - There is a new option "new-normalize" for dhall executable, which uses the new normalizer. - Type checker is unchanged.
0387b9b
to
fd5114b
Compare
- new implementation: alphaNormalize, judgmentallyEqual, normalize - normalizeWith takes a Maybe ReifiedNormalizer argument now, and switches to the new evaluator whenever the input normalizer is Nothing - QuickCheck test for isNormalized removed, because we don't support evaluation of ill-typed terms, which the test would require.
Updates:
I also tested Vanessa McHale's big file, and we only have about 25% checking time reduction on that so far. Small computation-heavy examples seem to get far greater speedups. So I believe currently the practically most relevant overheads are in type checking and imports. |
wow appveyor has reached the 1 hour limit build 😟 |
@jneira we should probably enable the cache on failed builds too, with |
@f-f maybe it could improve times in case of failed builds but i think the build times has increased since we are using ghc-8.6.4. |
dhall/src/Dhall/Eval.hs
Outdated
(VIntegerToDouble t , VIntegerToDouble t') -> convE t t' | ||
|
||
(VDouble , VDouble) -> True | ||
(VDoubleLit n , VDoubleLit n') -> n == n' |
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.
The standard requires slightly different behavior for equality of Double
literals. They are equal if their CBOR representation is equal. This is actually the case for all Dhall expressions (not just Double
s), but Double
literals happen to beone of the few cases where ordinary equality doesn't give the same behavior as CBOR equality.
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.
OK. I think now I should just export a doubleToTerm :: Double -> Term
function from Dhall.Binary
, and use that (I don't want to use encode
because of the unnecessary ToTerm
constraint on conv
; also, the next iteration of conv
will likely not have any class constraints, because it'll have access to Val
-s of imported expressions).
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.
Another way to do this without a ToTerm
constraint is to wrap the Double
value in a DoubleLit
constructor and then Dhall.Binary.encode
that
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.
Right, I realize now I just have to specify a suitable Expr s a
type for the DoubleLit
.
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 pushed a commit, I used encode
as you suggested.
dhall/src/Dhall/Eval.hs
Outdated
Merge x y ma -> case (evalE x, evalE y, evalE <$> ma) of | ||
(VRecordLit m, VUnionLit k v _, _) | ||
| Just f <- Dhall.Map.lookup k m -> f `vApp` v | ||
| otherwise -> error "eval: impossible" |
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.
Instead of returning error
, would it be possible to return the fallback case (i.e. VMerge x y ma
)? Then the property test in Dhall.Test.QuickCheck
could be re-enabled
Same comment for other uses of 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.
I prefer not being silent about type errors in evaluation. This is an important point for detecting obscure bugs in type checking. Also, once we compute past an ill-typed expression, totality of evaluation and soundness of conversion checking fail to hold.
BTW, I see now that Import.Types
has an InternalError
exception. Should I use that instead of these ad-hoc "impossible" errors? In this case I do intend to signal internal error, and not something like an obviously impossible branch. In Agda though, these are also called "impossible" errors.
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.
Yeah, you can use the Dhall.Core.internalError
function for this purpose. It provides a standard template for users to report implementation errors
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.
However, I like error
because it gives me line numbers, while throw InternalError
doesn't. Is there a way to get line numbers with thrown exceptions?
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.
Or just use error
with a nicer message...
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 used error
with nicer message in new commit.
I was curious to see how this performed with one project that is currently unusable with Dhall's current performance - replacing Nix with Dhall. The issue is at dhallix/nix-derivation#8. I updated the |
@ocharles: that's a very good benchmark, I'll keep it in mind. I did not expect dramatic speedup from this version, because the typechecker is not yet changed. I'm confident your example will get much faster after I do some work on type checking, which I plan to do relatively soon. |
Yeah, I know that on Vanessa's example, 80% of the time was spent in the type-checking phase so a 25% increase in performance on that example exactly matches the best case possible improvement without changing type-checking. |
I did wonder if that were the case. As I know this does type check, I may try dropping type checking out to see how much time is spent normalising. |
Ok, I think I've disabled the main type checking, and I see that |
@AndrasKovacs the Discourse link in your PR description is down, do you know where the information that was there can be found? Thanks. |
@ysangkok the Discourse history was deleted a while ago accidentally. Unfortunately I can't find the page now. Perhaps someone with more web cache/archive expertise can find it. |
See this post on discourse for motivation and background for this PR.
the new normalizer.
dhall/benchmark/examples/new-normalize
. There should be more benchmarks.