The internal_add
function tries to efficiently insert a latest range of integers into an existing list of sorted and disjoint integer ranges. For instance, if we began with [101..=102, 400..=402, 404..=405]
and added 402..=404
, we expect a results of [101..=102, 400..=405]
.
Ideally, I’d formally confirm this algorithm with Rust-specific tools [1,2]. Those tools, nevertheless, seem hard to make use of. As an alternative, I selected Dafny. Dafny is a language and verification system. It’s taught to undergraduates at universities world wide. It’s utilized in industry. I find it to be addictively interactive and programmer friendly.
Aside: Dafny creator, Dr. Rustan Leino has a connection to Rust beyond the coincidence of his first name. He helped create Spec#, the primary language to make use of a kind system to avoid null pointers. Rust, after all, adopted this concept to great success.
This text covers rules 1 to six. Part 2 will cover rules 7 to 9.
Before attempting to prove the mathematical correctness of your algorithm, resolve if the hassle is well worth the profit.
Dafny will not be Rust. Using Dafny requires porting algorithms of interest from Rust to Dafny. This port can miss details and introduce errors. Given this risk, should you use Dafny to confirm Rust algorithms? I boldly claim that “it depends”.
- How necessary is your algorithm’s correctness? For those who are printing a report and it looks right, it probably is correct. The
internal_add
algorithm relates to a knowledge structure that I’d like others to make use of with confidence, giving me extra motivation to confirm it. - Possibly all formal verification, with current tools, is just too hard. I feel, nevertheless, that Dafny makes formal verification as easy as currently possible. One can find formally verifying code easier in case you are already accustomed to types (for instance, from Rust) and recursion/induction (used infrequently in Rust). You may read this text and judge for yourself if/when formal verification is simple enough to be beneficial to you.
- Possibly fuzzing (reminiscent of
cargo-fuzz
) and property-based testing (reminiscent ofQuickCheck
) are adequate. Although these methods don’t provide mathematical certainty, they’re clever, useful, and straightforward to make use of. (Therange-set-blaze
crate already usesQuickCheck. See
Rule 9.5 in a previous article for details). - Possibly formal verification is and can at all times be doomed because writing a specification is as hard as writing code. I disagree. Take into consideration refactoring. I often start coding by writing something easy. I then refactor this straightforward code for efficiency. For
internal_add
, I discovered the specification to be simpler than any code. (You may judge this for yourself in Rule 4.)
Aside: Verification then becomes a computer-checked refactoring from a straightforward specification to a final, efficient algorithm.
- Possibly formal verification is and can at all times be doomed since the halting problem tells us formally that formality isn’t generally possible. The halting problem doesn’t doom us. While we are able to’t at all times understand arbitrary code, we don’t have to. We only need to know our own code, which we (hopefully) wrote to be comprehensible. Starting in Rule 2, we’ll see how Dafny easily verifies that specific loops and recursions halt.
- Possibly porting to Dafny is just too hard. This has not been my experience. Like Rust, Dafny mixes and matches imperative and functional programming. I discovered porting my algorithm to be straightforward.
Assuming you continue to wish to confirm your algorithm with Dafny, the next move is to learn Dafny.
Dafny is each a programming language and an interactive verification system. I like to recommend you install it as a VS Code extension.
To learn it, start at https://dafny.org/. Of special interest is the Online Tutorial and the Reference Manual. I also found the Verification Corner videos on YouTube helpful. (Of possible interest is the faculty textbook, Program Proofs, $49 for the Kindle Edition). I discovered the programming language a part of Dafny easier to learn than Rust, perhaps similar in difficulty to C#.
Dafny, like Rust, is fully typed. Dafny, like Python, is garbage collected. Here is a “Hello World”:
// hello.dfy
method Fundamental()
{
var s := "Hello World";
print s, "n";
}
Dafny, also like Python, offers integers of arbitrary size. Here is a program that provably adds two natural numbers by repeatedly incrementing.
calm music