Когда я компилирую приведенный ниже код Mercury, я получаю эту ошибку от компилятора:
In clause for `main(di, uo)':
in argument 1 of call to predicate
`test_with_anonymous_functions.assert_equals'/5:
mode error: variable `V_15' has
instantiatedness `/* unique */((func) =
(free >> ground) is semidet)',
expected instantiatedness was `((func) =
(free >> ground) is det)'.
Я думаю, что компилятор говорит: «Когда вы объявили тип test_case
, вы не указали детерминизм, поэтому я предположил, что вы имели в виду det
. Но затем вы передали лямбду semidet
».
Мои вопросы:
- Каков синтаксис для объявления детерминизма типа? Все догадки, которые я пробовал, приводили к синтаксическим ошибкам.
- Может кто-нибудь объяснить, что означает
/* unique */
часть инстанцированияTestCase
? Приведет ли это к несоответствию между заданным и ожидаемым экземпляром? - Есть ли менее подробный способ объявления лямбды в
main
? У меня столько же объявлений о лямбда-выражении, сколько и кода внутри лямбда-выражения.
Код:
% (Boilerplate statements at the top are omitted.)
% Return the nth item of a list
:- func nth(list(T), int) = T.
:- mode nth(in, in) = out is semidet.
nth([Hd | Tl], N) = (if N = 0 then Hd else nth(Tl, N - 1)).
% Unit testing: Execute TestCase to get the
% actual value. Print a message if (a) the lambda fails
% or (b) the actual value isn't the expected value.
:- type test_case(T) == ((func) = T).
:- pred assert_equals(test_case(T), T, string, io.state, io.state).
:- mode assert_equals(in, in, in, di, uo) is det.
assert_equals(TestCase, Expected, Message, !IO) :-
if Actual = apply(TestCase), Actual = Expected
then true % test passed. do nothing.
else io.format("Fail:\t%s\n", [s(Message)], !IO).
main(!IO) :-
List = [1, 2, 3, 4],
assert_equals( ((func) = (nth(List, 0)::out) is semidet),
1, "Nth", !IO).