Это действительно может сбить с толку!Здесь происходит несколько вещей:
Во-первых, помните, что Дафни рассуждает о каждом методе отдельно, используя только спецификации других методов.Так что в Main
единственное, что Дафни узнает о BinarySearchInsertionHint
, это его постусловия.Теперь получается, что hint == 4
на самом деле действительно следует из постусловий, но убедить Дафни в этом немного нетривиально.
Это подводит нас ко второму действию, происходящему здесь, которое является триггером-квантификатором.В постсекундах BinarySearchInsertionHint
используются универсальные квантификаторы (forall
), которые Дафни рассуждает об использовании синтаксической эвристики для создания экземпляров.Оба квантификатора в этом примере запускаются на a[i]
, что означает, что они не будут использоваться со значением v
, если a[v]
не находится в области действия для верификатора.
Вы можете получить утверждение, упомянув a[3]
и a[4]
, чего достаточно для Дафни из постусловий выяснить, что hint
должно быть 4
.Например:
method Main() {
var a := [0, 1, 1, 1, 2];
var hint := BinarySearchInsertionHint(a, 1);
assert a[3] == 1; // these assertions just "mention" a[3] and a[4]
assert a[4] == 2;
assert hint == 4; // assertion now passes
print hint;
}
Подробнее о модульных проверках Дафни, триггерах и неполных количествах можно узнать в Dafny FAQ .