Меркурий: этот предикат работает, если объявлен на верхнем уровне, но не как лямбда - PullRequest
0 голосов
/ 29 декабря 2018

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

Я определил вспомогательнуюПредикат существует двумя способами: один раз на верхнем уровне (называемый helper) и один раз как лямбда (называемый Helper).В последних трех строках кода ниже я использую этот вспомогательный предикат.Если я использую helper, это работает, но если я использую Helper, я получаю сообщение об ошибке (ниже).

Я подозреваю, что проблема может заключаться в том, что я могу указать сигнатуру типа, а также режимподпись для предиката уровня типа, но только сигнатура режима для лямбды.(Если это проблема, я не знаю, что с этим делать.)

Вот соответствующий код:

:- pred helper( query, int ).
:- mode helper( in, out ) is nondet.
helper( Q, F ) :-
  inQuery( fiveNumberSpace, Q, F ).

testQAnd = Res :-
    QQF = qqFind( qFind( list.filter( <(3) ) ) )
  , QQC = qqCond( qCond( func( Int )
                         = (if Int > 4 then no else yes) ) )
  , Helper = ( pred( Q :: in, F :: out ) is nondet :-
               inQuery( fiveNumberSpace, Q, F ) )

  % TODO Why can't I use Helper instead of helper for these?
  , solutions( helper( qqAnd( [QQF     ] ) ) , F1 )
  , solutions( helper( qqAnd( [QQF, QQC] ) ) , F2 )
  , solutions( helper( qqAnd( [     QQC] ) ) , F3 )

Вот ошибка, которую я получаю при использовании Helper:

Making Mercury/cs/test.c
test.m:098: In clause for function `testQAnd'/0:
test.m:098:   in argument 1 of call to predicate `solutions'/2:
test.m:098:   in unification of argument
test.m:098:   and term `Helper(V_34)':
test.m:098:   type error in argument(s) of higher-order term (with arity 1).
test.m:098:   Functor (Helper) has type `pred(query.query, int)',
test.m:098:   expected type was `((func V_13) = V_14)'.
** Error making `Mercury/cs/test.c'.

1 Ответ

0 голосов
/ 30 декабря 2018

У меня нет полного ответа на ваш вопрос, но я считаю, что это как-то связано с каррированием предиката.Я написал тестовый код, который запрашивает небольшую базу данных рыб.

:- pred fish(string::out, int::out) is multi.
fish("Red", 1).
fish("Blue", 2).
fish("Green", 3).

Этот помощник выдает ту же ошибку, что и выше:

Helper = (pred(S::in, L::out) is nondet :- fish(S, L)),
solutions(Helper("Red"), Sols)

Этот помощник работает нормально:

Helper2 = (pred(X::out) is nondet :- fish("Red", X)),
solutions(Helper2, Sols)

Я также попытался обернуть функцию решений.Это прекрасно работает:

:- func solutions_to(string) = list(int).
solutions_to(Color) = Answers :-
  P = (pred(X::out) is nondet :- fish(Color, X)),
  solutions(P, Answers).

Мне удалось написать предикат, который возвращал лямбда-предикат, однако я не смог написать функцию, которая бы делала то же самое.Здесь я начинаю путаться.Согласно этой странице вернуть предикат с информацией о режиме можно только в том случае, если вы преобразуете предикат в дискриминируемый тип объединения.Следующий код не очень полезен, но он позволяет одновременно

  1. реализовать лямбда-карри бедняков
  2. возвращает лямбда-предикат из функции

См .:

:- type inner
  ---> inner(pred(string:: out, int::out) is multi).
:- type wrapper
  ---> wrapper(pred(int::out) is nondet).

:- func make_pred(inner, string) = wrapper.
make_pred(Inner, Param) = P :-
  Inner = inner(I),
  P = wrapper(pred(X::out) is nondet :- I(Param, X)).

А затем использовать его:

Inner = inner((pred(X::out, Y::out) is multi :- fish(X, Y))),
WP = make_pred(Inner, "Red"),
WP = wrapper(P),
solutions(P, Sols),
...