Поддерживаются ли в Mercury алгебраические предикаты?

Я очень новичок в Mercury и логическом программировании в целом. Я не нашел такого числового примера в документах или примерах...

Возьмем пример предиката:

:- pred diffThirtyFour(float, float).
:- mode diffThirtyFour(in, out) is det.

diffThirtyFour(A,B) :-
    ( B = A + 34.0 ).

При этом А должен быть заземлен, а В свободен. Что, если я хочу, чтобы A был свободным, а B — заземленным (например, добавляя mode diffThirtyFour(out,in) is det.). Можно ли выполнять такую ​​алгебру во время компиляции? Я мог бы легко определить другой предикат, но это не кажется очень логичным...

Обновить

Итак, что-то вроде такого рода работ:

:- pred diffThirtyFour(float, float).
:- mode diffThirtyFour(in, out) is semidet.
:- mode diffThirtyFour(out, in) is semidet.

diffThirtyFour(A,B) :-
    ( B = A + 34.0, A = B - 34.0 ).

Немного опасаюсь semidet и избыточности второй цели. Это единственный способ сделать это?

Обновление 2

Это может быть ответом ... он выдает предупреждение во время компиляции о том, что дизъюнкт никогда не имеет решений. Правильное предупреждение, но, возможно, ненужный запах кода? Это делает то, что мне нужно, но если есть лучшие решения, не стесняйтесь публиковать их...

:- pred diffThirtyFour(float, float).
:- mode diffThirtyFour(in, out) is det.
:- mode diffThirtyFour(out, in) is det.



diffThirtyFour(A,B) :-
    ( A = B - 34.0, 
      B = A + 34.0 
    ; 
     error("The impossible happened...")
    ).

person m88    schedule 19.12.2017    source источник


Ответы (1)


Только что обнаружил возможность ввода разные условия для разных режимов. Это не совсем алгебраический решатель (чего я в любом случае не ожидал), но он предлагает точную организационную структуру, которую я искал:

:- pred diffThirtyFour(float, float).
:- mode diffThirtyFour(in, out) is det.
:- mode diffThirtyFour(out, in) is det.
:- pragma promise_pure(diffThirtyFour/2).

diffThirtyFour(A::out,B::in)  :- A = B - 34.0.
diffThirtyFour(A::in, B::out) :- B = A + 34.0.

Как описано в ссылке, прагма promise_pure требуется, поскольку эту функцию можно использовать для нарушения семантической согласованности. Также было бы достаточно использовать прагму promise_equivalent_clauses, которая обещает логическую согласованность без чистоты. По-прежнему можно объявлять предложения с непоследовательной семантикой с помощью ключевого слова impure в объявлении pred.

Интересно, что сложение и вычитание в стандартном модуле int обратимы, но не в модуле float. Возможно, выбор был сделан из-за возможных ошибок в арифметике с плавающей запятой....

person m88    schedule 22.12.2017