我编写了一个表示集合S上的二元关系的类,它有两个字段:set,S和从S中抽取的第二组值。该类定义了一堆关系属性,例如是单值(即,作为函数,如“isFunction()”谓词中定义的)。在类定义之后,我尝试定义一些子集类型。一种意思是定义这些关系的子类型,它们实际上也是“函数”。它不起作用,解码生成的错误代码有点困难。请注意,Valid()和isFunction()谓词确实声明“读取此内容”。关于我应该在哪里寻找的任何想法?是不是Dafny不能说子集类型是有人居住的?有没有办法说服它呢?
public class FindActivity extends FragmentActivity implements LoaderManager.LoaderCallbacks<Cursor>, ListChooserDialogListener
{
[Dafny VSCode]尝试见证null:操作结果可能违反'binRelOnS'的子集类型约束
答案 0 :(得分:1)
表单的子集类型定义
type MySubset = x: BaseType | RHS(x)
引入MySubset
作为一种类型,代表满足布尔表达式x
的类型BaseType
的值RHS(x)
。由于Dafny中的每个类型都必须是非空的,因此有证据证明您声明的类型具有某个成员。 Dafny可能会找到一些候选值,并会尝试查看其中任何一个是否满足RHS
。如果候选人没有,你会收到一条错误消息,就像你看到的那样。有时,错误消息会告诉您Dafny尝试了哪些候选值。
在您的情况下,Dafny尝试的唯一候选值是值null
。正如James指出的那样,值null
甚至没有达到一垒,因为示例中的BaseType
是一种非空引用。如果您将binRelOnS<T>
更改为binRelOnS?<T>
,则null
有可能成为可能的证人,表明您的子集类型是非空的。
由于Dafny对于提出候选人证人并不太聪明,你可能需要自己提供一个。您可以通过在声明末尾添加witness
子句来完成此操作。例如:
type OddInt = x: int | x % 2 == 1 witness 73
由于73
满足RHS约束x % 2 == 1
,因此Dafny接受此类型。在某些程序中,您可能会想到只有鬼代码才能使用您的见证。然后,您可以编写ghost witness
而不是witness
,这允许后续表达式为ghost。 ghost见证可以用来说服Dafny验证器类型是非空的,但它不能帮助Dafny编译器初始化该类型的变量,因此您仍然需要自己初始化这些变量。
使用witness
子句,您可以尝试使用子集类型func
的原始定义来提供自己的见证。但是,见证子句采用表达式而不是语句,这意味着您无法使用new
。如果你不关心编写你的程序,并且你愿意相信自己对证人的存在,你可以声明一个无体功能,承诺返回一个合适的证人:
type MySubset = x: BaseType | RHS(x) ghost witness MySubsetWitness()
function MySubsetWitness(): BaseType
ensures RHS(MySubsetWitness())
您需要ghost witness
或function method
。函数MySubsetWitness
将永远留在没有正文的情况下,因此您可以在某个值满足RHS
的情况下犯错误。
Dafny版本2.0.0中引入了witness
子句。 2.0.0 release notes提到了这一点,但显然没有给出太多解释。如果您想查看witness
的更多示例,请在Dafny test suite中搜索该关键字。
在您的示例中,如果将基本类型更改为可能为null的引用类型:
type func<T> = f: binRelOnS?<T> | f.Valid() && f.isFunction()
然后您的下一个问题是RHS解除引用f
。您可以通过弱化子集类型约束来解决此问题,如下所示:
type func<T> = f: binRelOnS?<T> | f != null ==> f.Valid() && f.isFunction()
现在可能是交易破坏者的部分。子集类型不能依赖于可变状态。这是因为类型是一个非常静态的概念(与规范不同,通常取决于状态)。如果一个值可以满足一个类型的时刻,然后在程序中的一些状态更改之后,不满足该类型,那将是一场灾难。 (实际上,几乎所有具有子集/细化/依赖类型的类型系统都是用于函数式语言。)因此,如果您的Valid
或isFunction
谓词具有reads
子句,那么您无法定义{以你希望的方式{1}}但是,只要func
和Valid
都只依赖于类中isFunction
个字段的值,就不需要const
子句,而且你都已经设置好了。< / p>
Rustan