Пролог Предикат понижения высшего порядка
Мы можем определить предикат карты высшего порядка как:
map([], [], F).
map([A|As], [B|Bs], F) :-
call(F, A, B),
map(As, Bs, F).
Точно так же мы можем определить сгиб (слева) как:
fold([], Acc, Acc, _F).
fold([A|As], B, Acc1, F) :-
call(F, Acc1, A, Acc2),
fold(As, B, Acc2, F).
Какое правильное определение для снижения (слева)? Можем ли мы определить это следующим образом?
reduce([A|As], Bs, F) :-
fold(As, Bs, A, F).
И уменьшить (справа) следующим образом?
reduceback([], Ident, F) :-
identity(F, Ident).
reduceback([A|As], B, F) :-
reduceback(As, C, F),
call(F, C, A, B).
Это правильно?
1 ответ
Свернуть /4 и уменьшить /3 работают правильно, в то время как без идентификатора /1 сокращение /3 является неполным. Но поток управления кажется правильным, хотя
1 ?- fold([1,2,3],S,0,[X,Y,Z]>>(Z is X+Y)).
S = 6.
2 ?- reduce([1,2,3],S,[X,Y,Z]>>(Z is X+Y)).
S = 6.
Я добавил декларации
:- метаданные предикаты (+,?,+,3).:- meta_predicate уменьшить (+,?,3).
которые квалифицируют аргументы как замыкания и используют библиотеку ( yall) для лямбда-выражений...
В Прологе общепринятым условием является указание выходных аргументов последними, поэтому ваши определения довольно нечитаемы для меня...
редактировать
для симметрии с редуктом /3, идентичность /1 кажется бесполезной, вместо нее можно использовать последний элемент:
:- meta_predicate reduceback(+,?,3).
reduceback([Last],Last,_F).
reduceback([A|As],B,F):-
reduceback(As,C,F),
call(F,C,A,B).
тестовое задание:
?- reduceback([1,2,3],S,[X,Y,Z]>>(Z is X+Y)).
S = 6 ;
false.
?- reduceback([1,2,3],S,[X,Y,Z]>>(Z is X-Y)).
S = 0 ;
false.