自然会认为 Dafny 静态验证器可以
评估任何代码,例如您的断言语句中的表达式。这
验证器确实尝试评估这样的表达式,其中
参数以常量形式给出(如您的"hello world"、'l'、
和3)。但是,静态验证者希望避免递归
永远(甚至递归太久),所以它并不总是完全
通过这些表达式。在你的情况下,也有限制
验证者能够对序列操作做什么。所以,在
简而言之,尽管验证者试图提供帮助,但并不总是
深入递归。
您可以通过两种方式绕过这些限制来获得
验证者接受您的断言。
调试情况最可靠的方法是从较小的开始
输入并建立到您正在使用的更长输入。这是相当
然而,这很乏味,当达夫尼能够做到时,它会让你很感激
这些东西是自动的。以下(验证)
说明你会做什么:
var s := "hello world";
assert tally("he",'l') == 0;
assert tally("hel",'l') == 1;
assert "hell"[..3] == "hel";
assert tally("hell",'l') == 2;
assert "hello"[..4] == "hell";
assert tally("hello",'l') == 2;
assert "hello "[..5] == "hello";
assert tally("hello ",'l') == 2;
assert "hello w"[..6] == "hello ";
assert tally("hello w",'l') == 2;
assert "hello wo"[..7] == "hello w";
assert tally("hello wo",'l') == 2;
assert "hello wor"[..8] == "hello wo";
assert tally("hello wor",'l') == 2;
assert "hello worl"[..9] == "hello wor";
assert tally("hello worl",'l') == 3;
assert s[..10] == "hello worl";
assert tally(s,'l') == 3;
其实 Dafny 验证器没有扩展的东西(太多
次)对你来说是“采取”操作(即
表格s[..E])。以下中间断言也将
验证自己并将有助于验证最终断言。这些
中间断言显示验证者不认为做什么
自动为您服务。
var s := "hello world";
assert "he"[..1] == "h";
assert "hel"[..2] == "he";
assert "hell"[..3] == "hel";
assert "hello"[..4] == "hell";
assert "hello "[..5] == "hello";
assert "hello w"[..6] == "hello ";
assert "hello wo"[..7] == "hello w";
assert "hello wor"[..8] == "hello wo";
assert "hello worl"[..9] == "hello wor";
assert s[..10] == "hello worl";
assert tally(s,'l') == 3;
您可能想知道,“我到底怎么会想出这个?”。这
最系统的方法是从我上面的第一个例子开始。
然后,您可以尝试修剪那里的许多断言,看看它是什么
是验证者需要的。
(我现在想也许可以将 Dafny 验证器增强为
也做这些操作。它可能会导致性能问题
别处。我去看看。)
解决验证者限制的另一种方法是定义
以不同的方式运行tally,特别是避免“采取”
操作,验证者不想扩展很多。它是
不清楚要改变什么来让验证者对这些感到满意
情况,或者如果这甚至可能的话,所以这个解决方法可能
不是最好的。不过,我尝试了以下定义
tally 它使您的断言通过:
function method tally'(s: string, letter: char): nat
{
tally_from(s, letter, 0)
}
function method tally_from(s: string, letter: char, start: nat): nat
requires start <= |s|
decreases |s| - start
{
if start == |s| then 0
else (if s[start] == letter then 1 else 0) + tally_from(s, letter, start+1)
}
请注意,这些定义不使用任何“take”操作。这里,
验证者很乐意扩展所有递归调用,直到
终于找到答案了。
鲁斯坦