-
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
optimize Natural/fold in the strict case #2585
optimize Natural/fold in the strict case #2585
Conversation
Co-authored-by: Gabriella Gonzalez <[email protected]>
@Gabriella439 Thank you for the suggestion. I'm not sure why the build fails for MacOS. I also have trouble building Update - this is fixed now. |
@Gabriella439 My changes do not actually seem to work. I built a local executable ( let f : Natural → Natural = λ(x : Natural) → if Natural/isZero x then 1 else x
in Natural/fold 100000000 Natural f 0 takes about 5 seconds but should be instantaneous. Am I doing something wrong? I changed the Dhall version to 1.42.2 in $ stack build dhall
...
Installing executable dhall in /Users/sergei.winitzki/Code/winitzki-dhall-haskell/.stack-work/install/x86_64-osx/5cb58a553262eb646270303a92d2143ba964e30fb089950b829eb0787bd00e99/9.2.8/bin
Registering library for dhall-1.42.2..
$ stack exec dhall repl
Welcome to the Dhall v1.42.2 REPL! Type :help for more information.
⊢ :let f : Natural → Natural = λ(x : Natural) → if Natural/isZero x then 1 else x
f : Natural → Natural
⊢ Natural/fold 100000000 Natural f 0
1 This still takes about 5 seconds. How could this even work if I compiled dhall with no code for Am I editing the wrong place in the source code? I see that some code involving |
I added some new code to Why is For |
@Gabriella439 You merged the PR but I still think the work is not finished. See my comment in the code. |
in go zero (fromIntegral n' :: Integer) | ||
go zero (fromIntegral n' :: Integer) where | ||
go !acc 0 = acc | ||
go (VNaturalLit x) m = |
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.
Here, we detect the shortcut only when the accumulator is a Natural
literal. However, we would like to detect the shortcut in all cases. I could not find any way of comparing Val
values. What kind of code would need to be written 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.
Dhall.Eval.conv
is what you want
The proposed optimization follows the discussion in dhall-lang/dhall-lang#1213 (comment)
The beta-normalization for
Natural/fold n t succ zero
corresponds to evaluatingsucc(succ(succ(...(succ(zero))...)))
where we applysucc
exactlyn
times.The current code uses a loop where
succ
is always evaluatedn
times.However, sometimes the loop can be stopped early because the values stop changing.
For example:
With this definition, we have
f x = x
when x is nonzero. The expression evaluates to 5, but the evaluation takes time linear in the first argument (10000000) because the functionf
will be applied that many times to the value5
and beta-normalization will be performed each time.The new code rewrites
strictLoop
viastrictLoopShortcut
, which stops the loop as soon asf x = x
.This optimization is only applied in the "strict" case (
Normalization.hs
introducesstrict
andlazy
cases when evaluatingNatural/fold
.)There should be no change of behavior after this optimization.
This is because all Dhall functions are pure; if
f x = x
then the result of evaluatingf (f (f x))
is exactly the same as justx
.So, the only effect of the new code is that some
Natural/fold
expressions will be beta-normalized faster than before.I'd like to add some tests for the new behavior but I don't know how. The new behavior returns exactly the same normal forms as before, but does it faster when the "shortcut" is detected (when
f x = x
is detected). I am not a Haskell programmer, so any suggestions will be welcome here.Another issue is that I am not familiar with the Haskell build systems, and both
cabal new-build dhall
as well asstack build
fail on my machine in this project, with dependency errors that I am unable to fix.