Общее программирование на Прологе

Насколько мне известно, в Прологе нет встроенных механизмов для универсального программирования. Можно имитировать дженерики с помощью унификации, но для этого требуется проверка типов во время выполнения:

:- initialization(main).
:- set_prolog_flag(double_quotes, chars).

% this is a "generic" predicate, where A and B have the same type
add(A,B,C) :-
    generic_types([A:Type,B:Type]),
    (Type = number,
    C is A + B;Type=var,C = A+B).

main :-
    add(A,B,C),
    add(3,4,D),
    writeln(C),
    writeln(D).

generic_types([]).
generic_types([A:B|C]) :-
    member(B,[var,nonvar,float,rational,number,atom,atomic,compound,callable,ground,acyclic_term]),
    call(B,A),
    generic_types(C).
has_type(Type,A) :-
    call(Type,A).

Можно ли написать «общие» предикаты без проверки типа каждой переменной во время выполнения?


person Anderson Green    schedule 21.09.2019    source источник
comment
Пролог динамически типизирован. Так что проверки типов не так много, как в Python.   -  person Willem Van Onsem    schedule 21.09.2019
comment
Это немного похоже на вопрос о том, как можно смоделировать сцепление в автомобиле с автоматической коробкой передач. Общее программирование само по себе применимо только к языкам со статической проверкой типов. Каждый предикат Пролога уже является универсальным с точки зрения типов, которые он принимает, и в Прологе нет другой проверки типов, кроме времени выполнения. Такая же ситуация в Python и любом другом языке с динамической типизацией. Система типов Python не имеет разветвлений на семантику программ Python или их оценку по своему замыслу.   -  person Daniel Lyons    schedule 21.09.2019
comment
Небольшое замечание: типы, имеющие смысл в вашем случае, не включают var. См. это для получения дополнительной информации.   -  person false    schedule 22.09.2019


Ответы (2)


Некоторые формы общего программирования доступны на Прологе через Logtalk, который расширяет Пролог и может использоваться с большинством систем Пролога.

Учитывая, что вы хотите использовать разные определения предиката add/3 в зависимости от типа первых двух аргументов, мы можем начать с определения протокола, объявляющего предикат:

:- protocol(math_protocol).

    :- public(add/3).

:- end_protocol.

Основываясь на вашем образце кода, теперь мы можем определить различные реализации предиката:

:- object(number,
    implements(math_protocol)).

    add(A, B, C) :-
        C is A + B.

:- end_object.


:- object(var,
    implements(math_protocol)).

    add(A, B, C) :-
        C = A + B.

:- end_object.

Мы можем изменить объекты number и var, чтобы они также выполняли проверку типов. Например:

:- object(number,
    implements(math_protocol)).

    add(A, B, C) :-
        number(A),
        number(B),
        C is A + B.

:- end_object.

В качестве альтернативы мы можем определить параметрический объект для типа, который выполняет проверку типа, а затем делегирует фактическую операцию над типом. Например:

:- object(math(_Type_),
    implements(math_protocol)).

    add(A, B, C) :-
        call(_Type_, A),
        call(_Type_, B),
        _Type_::add(A, B, C).

:- end_object.

Пример вызова в этом случае будет таким:

?- math(number)::add(2, 3, Sum).
Sum = 5
yes

Но обратите внимание, что эти альтернативы по-прежнему будут выполнять проверку типов во время выполнения.

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

person Paulo Moura    schedule 02.05.2021

Вы можете эмулировать параметрический полиморфизм, явно добавляя параметр типа к предикату:

add(int, A, B, C) :-
    C is A + B.
add(var, A, B, C) :-
    C #= A + B.


?- add(var, 2, 3, 5).
true.

?- add(var, A, 3, 5).
A = 2.

?- add(int, A, 3, 5).
ERROR: Arguments are not sufficiently instantiated
person Erik Kaplun    schedule 02.05.2021
comment
Вместо передачи типа в качестве параметра вы также можете использовать предикаты проверки типов Пролога. - person Anderson Green; 02.05.2021