Хорошие вопросы!Вы столкнулись с некоторыми известными острыми краями в Dafny, которые недостаточно документированы.
В первой ошибке Dafny в основном говорит, что переменная типа K
должна быть ограничена, чтобы не быть ссылочным типом.Вы можете сделать это, изменив сигнатуру функции, чтобы она начиналась с
function update_map<K(!new), V>...
Здесь (!new)
- это синтаксис Дафни, означающий, что экземпляр K
может быть создан только с типами значений, а не ссылочными типами.(К сожалению, !new
еще не задокументировано, но есть открытый выпуск об этом.)
Во второй ошибке вы сталкиваетесь с ограниченной синтаксической эвристикой Дафни, чтобы доказать конечность, как описано в этом вопрос и ответ .Исправление заключается в использовании встроенного оператора объединения Dafny вместо логического дизъюнкции, например:
map k | k in m1.Keys + m2.Keys :: ...
(Здесь я использую .Keys
для преобразования каждой карты в набор ключей в своей области, такчто я могу применить +
, который работает на наборах, но не на картах.)
С этими двумя исправленными ошибками времени проверки типов теперь вы получаете две новые ошибки времени проверки.Yay!
stdin.dfy(3,45): Error: element may not be in domain
stdin.dfy(4,59): Error: element may not be in domain
Они говорят вам, что утверждение самого постусловия неверно, потому что вы индексируете карты, используя ключи без правильной гипотезы, что эти ключи находятся в области карты.Вы можете исправить это, добавив еще одно постусловие ( до других), например:
(forall k :: k in m1 || k in m2 ==> k in update_map(m1, m2)) && ...
После этого вся функция проверяет.