【发布时间】:2022-01-24 19:22:36
【问题描述】:
有没有办法说高阶函数允许对它作为参数的函数设置先决条件?
这是我要解决的具体情况。我编写了这个函数,用于根据谓词过滤seq 中的项目:
function method filterSeq<T>(s: seq<T>, fn: T -> bool): seq<T>
ensures forall i | 0 <= i < |filterSeq(s, fn)| :: fn(filterSeq(s, fn)[i]) == true
ensures forall i | 0 <= i < |filterSeq(s, fn)| :: filterSeq(s, fn)[i] in s
ensures forall i | 0 <= i < |s| :: fn(s[i]) ==> s[i] in filterSeq(s, fn)
{
if |s| == 0 then [] else (
if fn(s[0]) then [s[0]] + filterSeq(s[1..], fn) else filterSeq(s[1..], fn)
)
}
这涵盖了我关心的后置条件,但没有说明fn 的论点。我想说,对于在s 中适用于所有T 的任何属性,此属性是允许作为fn 的前提条件的。
导致我出现此问题的问题是尝试过滤包含其他序列的序列:
var sequences := [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
assert forall i | 0 <= i < |sequences| :: |sequences[i]| == 3;
var result := filterSeq(sequences, sequence => sequence[0] == 4);
当我尝试这个时,我在sequence[0] 上收到一个错误,上面写着index out of range。很公平,我尝试为 lambda 添加一个先决条件:
var sequences := [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
assert forall i | 0 <= i < |sequences| :: |sequences[i]| == 3;
var result := filterSeq(sequences,
sequence requires |sequence| == 3 => sequence[0] == 4);
现在我在 lambda 参数上收到错误 value does not satisfy the subset constraints of 'seq<int> -> bool' (possible cause: it may be partial or have read effects)。这也是有道理的,我传递了一个部分函数,我在其中为非部分函数编写了类型签名。
我的问题是:如何更改 filterSeq 以允许这样做?我可以以某种方式编写它以便它可以在任意前提条件下工作,还是我必须编写一个单独的 filterSeqOfSequences 方法来涵盖这个特定的用例?
【问题讨论】:
标签: dafny