Мне также потребовалось некоторое время, чтобы освоиться.
Проблема в том, что режим члена более высокого порядка является , а не частью его типа.Таким образом, нет синтаксиса для объявления детерминизма типа.Детерминизм термина высшего порядка переносится в режиме.
В вашем примере первый аргумент assert_equals
имеет тип test_case(T)
, но имеет режим in
.Это означает, что тот факт, что функция semidet
теряется.Я не уверен, что он действительно скомпилируется или будет работать правильно, если передаваемая вами функция будет det
;даже в этом случае режим действительно не должен быть in
.
Вот пример:
:- pred apply_transformer(func(T) = T, T, T).
:- mode apply_transformer(func(in) = out is det, in, out).
apply_transformer(F, X0, X) :-
X = F(X0).
main(!IO) :-
apply_transformer((func(S0) = S is det :- S = "Hello " ++ S0),
"World", Msg),
print(Msg, !IO),
nl(!IO).
Как видите, тип первого аргумента для apply_transformer
толькоговорит, что это функция высшего порядка, принимает один аргумент и возвращает результат того же типа.Это объявление режима, которое на самом деле говорит, что параметр функции имеет режим in
, а результат функции имеет режим out
, а его детерминизм равен det
.
Я полагаю, что бит /*unique */
ошибкиСообщение говорит, что компилятор считает, что это уникальное значение.Я не уверен, является ли это проблемой или нет, поскольку вы не используете уникальные режимы нигде, кроме обычного состояния io
.
Что касается лямбда-синтаксиса, я не думаю, что вы можете сделатьлучше, к сожалению.Я нахожу синтаксис лямбд в Меркурии довольно неудовлетворительным;они настолько многословны, что я обычно просто делаю именованные функции / предикаты вместо всех, кроме самых тривиальных лямбд.