在Mercury中,我可以聲明一個lambda具有與包含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
中的lambda表達式被聲明爲det,所以他們不能調用semidet Pred
。如果我將lambda轉換爲semidet,那麼整個fold
不能被det。
我該如何解決這個問題?看起來最直接的方法是聲明lambda表達式繼承它們的謂詞決定論 - 所以它們在fold
被用作det時也是如此,但是我不知道這是否可能。
當然,另一種方法是將FoldRows
和FoldCols
轉換爲具有多種模式的命名謂詞(不是lambda表達式)。但這很快就變得不雅,我想知道是否有更直接的解決方案。