Skip to content
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

Standard libraries #22

Merged
merged 19 commits into from
Dec 20, 2023
Merged

Standard libraries #22

merged 19 commits into from
Dec 20, 2023

Conversation

robin-aws
Copy link
Member

No description provided.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I experimented with this in the hopes I could use pandoc to get Dafny snippet highlighting, but haven't got it working yet: it seems to tag all the right code elements with the right classes, but doesn't emit any of the dynamically generated CSS anywhere for some reason.

Or perhaps you were distracted by the `Std.Strings` module, where you might expect these utilities to live.
But in Dafny, strings are really nothing more than sequences of characters:
the type `string` is just an alias for `seq<char>`.
This means many typical string operations are provided as general sequence operations instead.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That sounds like a design issue. Could we have a module Strings refines Seq so that we not only provide everything Seq provides, but it's discoverable and extensible? I see how methods such as ToUpperCase could be in such a module.

If you agree with this, you can just resolve this comment by cutting an appropriate issue.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree there's room for improvement here in some way, and I cut this issue with several thoughts that came up while writing this: dafny-lang/dafny#4878

the execution of the function body will immediately stop,
and that failure will become the result of the whole function.
At this point we have a valid Dafny program, and the IDE should reward our hard work
with [a festive green gutter](https://dafny.org/blog/2023/04/19/making-verification-compelling-visual-verification-feedback-for-dafny)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😍

Dafny actually **knows** that they return the indexes of elements that satisfy the "by" predicate,
and therefore deduces that `[line[firstDigitIndex], line[lastDigitIndex]]`
is a string that only contains digits.
I don't know about you but I think that's super cool.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yeah that's excellent to highlight!

method ReadPuzzleInput() returns (input: Wrappers.Result<string, string>) {
var bytesAsBVs :- FileIO.ReadBytesFromFile("input.txt");

var bytes := seq(|bytesAsBVs|, i requires 0 <= i < |bytesAsBVs| => bytesAsBVs[i] as BoundedInts.uint8);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's unfortunate we need to do this conversion. We ought to be able to just cast. Anyway.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, also noted in dafny-lang/dafny#4878

A few notes:

* The `UnicodeStringsWithUnicodeChar` module is named that way to emphasize that it is only
correct to use with the `--unicode-char:true` mode, which is [on by default in Dafny 4.x](https://dafny.org/blog/2023/03/03/dafny-4-released/#unicode-strings).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
correct to use with the `--unicode-char:true` mode, which is [on by default in Dafny 4.x](https://dafny.org/blog/2023/03/03/dafny-4-released/#unicode-strings).
correct to use with the `unicode-char=true` option, which is [on by default in Dafny 4.x](https://dafny.org/blog/2023/03/03/dafny-4-released/#unicode-strings).

Since you are using the dfyconfig.toml :-)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point - I think I'll call out the difference in syntax earlier and mention both forms here.

in the main method than printing an error and exiting.
`:- expect` means that if the right-hand side of the statement is a failure,
Dafny will immediately halt and print the failure value to the console.
This is particularly valuable for writing tests in Dafny.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just discovered that tests can return failure-compatible types as well so you can use :- without expect. Not sure if it's worth mentioning here but perhaps in the future.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed I'm still debating whether to frame the solution a little differently. As soon as I added the CI check of the solution I thought "this should really be a {:test} instead of a Main method". But on the other hand in the puzzle solving context you don't actually know the answer so you do need a Main method you just run as well, plus I feel like printing out the answer is just more exciting than a passing test case. :)

In fact I think I'll actually call this out explicitly and do both, since I'm already calling out similar Real Code issues outside of the puzzle context anyway.

% dafny run dfyconfig.toml

Dafny program verifier finished with 3 verified, 0 errors
142
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I got the same result too! good job :-)

(see below for the complete program),
all thanks to the Dafny standard libraries.

```dafny
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you use import statements like John's blog post, so that you can verify this piece of code?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still trying to figure out the best way to do that and get nice syntax highlighting on the snippets. I'm not using Madoko and trying to find a more standard solution, hence experimenting with pandoc. My fallback approach will be to use the verification-compelling-verification-steps.js script and the {% include ... %} directives it supports, as the most recent post did.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ended up switching to Madoko and just including the final solution source, so at least that is continuously checked. It didn't seem worth it to convert the other snippets to source since they aren't complicated, and some are not even expected to be valid since they are partial work-in-progress.

@robin-aws robin-aws marked this pull request as ready for review December 18, 2023 22:02
@ssomayyajula ssomayyajula self-requested a review December 19, 2023 16:46
Copy link

@ssomayyajula ssomayyajula left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall!

_posts/2023-12-20-standard-libraries.markdown Outdated Show resolved Hide resolved
_posts/2023-12-20-standard-libraries.markdown Outdated Show resolved Hide resolved
_posts/2023-12-20-standard-libraries.markdown Outdated Show resolved Hide resolved
_posts/2023-12-20-standard-libraries.markdown Outdated Show resolved Hide resolved
_posts/2023-12-20-standard-libraries.markdown Outdated Show resolved Hide resolved
_posts/2023-12-20-standard-libraries.markdown Outdated Show resolved Hide resolved
Copy link
Member

@MikaelMayer MikaelMayer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only two comments! I loved the very casual introduction of this blog post and the fact that you made it entertaining throughout, with appropriate links and comments about anything readers might be wondering. Left me with a sense of happiness.

assets/mdk/standard-libraries.mdk Outdated Show resolved Hide resolved
in the main method than printing an error and exiting.
`:- expect` means that if the right-hand side of the statement is a failure,
Dafny will immediately halt and print the failure value to the console.
This is particularly valuable for writing tests in Dafny.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
This is particularly valuable for writing tests in Dafny.
This is particularly valuable for writing tests in Dafny, but don't use it in production code!

Or something similar implying that we should not use expect statements anywhere else normally. Not like Rust's unwrap for example.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That version is a bit strong but I pushed my own only slightly softer variation. :)

@robin-aws robin-aws merged commit 651a721 into main Dec 20, 2023
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants