Сопоставление детерминизма лямбды и предиката в Mercury

Могу ли я в Mercury объявить лямбду как имеющую тот же детерминизм, что и модус предиката, содержащего лямбду?

Вот что я пытаюсь сделать. Я написал функцию fold (ниже), которая работает с типом 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 объявлены как det, поэтому они не могут вызывать semidet Pred. Если я поменяю лямбды на полудет, то fold в целом не может быть дет.

Как я могу решить эту проблему? Кажется, самым простым подходом было бы объявить, что лямбда-выражения наследуют свой детерминизм от предиката fold — поэтому они являются det, когда fold используется как det, аналогично для semidet — но я не знаю, возможно ли это. .

Другой подход, конечно, состоит в том, чтобы превратить FoldRows и FoldCols в именованные предикаты (не лямбда-выражения) с несколькими режимами. Но это быстро становится неэлегантным, и мне интересно, есть ли более простое решение.


person Evan    schedule 31.10.2014    source источник


Ответы (1)


Меркурий иногда может вывести модусы и детерминизмы предикатов, поэтому я сначала попытался это сделать, опуская объявление детерминизма из лямбда-выражений. Однако лямбда-синтаксис Mercury не позволяет мне это сделать, поэтому этот вывод нельзя использовать с лямбда-выражениями.

Боюсь, что единственное решение, как вы уже догадались, состоит в том, чтобы превратить FoldRows и FoldCols в многорежимные именованные предикаты.

person Paul Bone    schedule 04.11.2014