在水星中匹配lambda和谓词的确定性

时间:2014-10-31 21:51:05

标签: lambda non-deterministic mercury

在Mercury中,我可以将lambda声明为与包含lambda的谓词模式具有相同的确定性吗?

这就是我想要做的。我写了一个折叠函数(下面),它适用于array2d类型。 fold为数组中的每个元素调用一个调用者提供的谓词。它工作正常,只要它只接受一个det谓词作为参数。

:- pred fold(array2d(T), pred(T,  int, int, A, A),              A,  A).
:- mode fold(in,         pred(in, in,  in, in, out) is det,     in, out) is det.
% Uncommenting the next line causes mode errors during compilation
% :- mode fold(in,       pred(in, in,  in, in, out) is semidet, in, out) is semidet.

fold(Array, Pred, !Accumulator) :-
    bounds(Array, NumRows, NumCols),

    FoldRows = (pred(RowNumber :: in, RowAccIn :: in, RowAccOut :: out) is det :-
        FoldCols = (pred(ColNumber :: in, ColAccIn :: in, ColAccOut :: out) is det :-
            Value = Array^elem(RowNumber, ColNumber),
            Pred(Value, RowNumber, ColNumber, ColAccIn, ColAccOut)
        ),
        int.fold_up(FoldCols, 0, NumCols - 1, RowAccIn, RowAccOut)
    ),
    int.fold_up(FoldRows, 0, NumRows - 1, !Accumulator).

但我希望fold接受det或semidet谓词(如果对谓词的任何调用失败,则会失败)。取消注释mode ... is semidet行会给我编译错误,我不知道如何解决。问题是fold中的lambdas被声明为det,所以他们不能调用semidet Pred。如果我将lambda改为semidet,那么整个fold就不能解除。

我该如何解决这个问题?似乎最直接的方法是声明lambdas从fold谓词继承它们的确定性 - 所以当fold被用作det时它们是det,同样对于semidet - 但是我不知道这是否可能。

当然,另一种方法是将FoldRowsFoldCols转换为具有多种模式的命名谓词(而不是lambdas)。但这很快变得不那么优雅了,我想知道是否有更直接的解决方案。

1 个答案:

答案 0 :(得分:1)

Mercury有时可以推断谓词的模式和确定性,所以我最初通过省略lambda表达式中的determinism声明来尝试这一点。但是,Mercury的lambda语法不允许我这样做,所以这个推论不能用于lambdas。

我担心,正如您所猜测的那样,唯一的解决方案是将FoldRows和FoldCols转换为多模式命名谓词。