2008-11-18 9 views
15

В настоящее время я работаю над очень коротким проектом на Prolog и просто застрял, пытаясь применить «фильтр», который я создал к списку. У меня есть то, что вы могли бы назвать фильтром готовым, но я не могу его применить. Было бы лучше, если бы я проиллюстрировал:Пролог: Фильтрация списка?

filter(A, B) 

... выдает «true», если выполняются определенные условия.

filterList(A, [X, Y, Z]) 

... выводит список, который включает все элементы из второго аргумента, которые делают вывод фильтра ложной. (Таким образом, если фильтр (A, X) истинен, выходной сигнал [Y, Z]).

У меня есть функция «фильтр», но теперь мне нужно применить ее к списку, как показано на втором примере, за исключением всех элементов, для которых фильтр возвращает true при применении с первым аргументом.

Итак, если фильтр является простым A == B, функция должна получать A [A, B, A, C, D, A] и выводить [B, C, D], удалив все элементы, для которых применяется фильтр.

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

Заранее благодарен!

ответ

11

Если вы ищете функции высшего порядка в Прологе, вы должны определенно консультироваться Naish (1995), очень хороший ресурс по этому поводу.

Его определение filter/3 следующий (он использует разностной список обозначений, поэтому ускользает необходимости определять filter/4):


filter(_,[],[]). 
filter(P, A0-As0, As) :- 
    (
     call(P, A0) -> As = A0-As1 
    ; 
     As = As1 
    ) 
    , filter(P, As0, As1). 

Я у вас есть вопросы по поводу этого предиката, пожалуйста, спросите меня в комментарии , Чтение бумаги также рекомендуется, это также проблема map, foldr и compose! Обратите внимание, что многие из ограничений, которые он упоминает (например, отсутствующие call/3 или более высокий порядок apply больше не применяются. В SWI-Prolog есть оператор =.., который учитывает все его проблемы и делает возможной логику логики n-порядка.

+1

Питти Наиш предлагает применить/3 в своих выводах, но я предполагаю, что в настоящее время нужно использовать call/n. apply/3 - просто вызов/3. – 2011-12-09 18:01:51

+2

См. Обсуждение вопроса о том, почему ссылка на Naish оспаривается: http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/naish.html – 2011-12-10 16:17:49

0

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

filterList(_,[],R,R).   % Returns answer when the list is exhausted. 
filterList(L,[A|List],Temp,Res) :- 
    filterList(L,List,New,Res), % Recursive call, New is either the same list 
    ( filter(L,A),    % in case the filter outputs true, or the list 
     New = Temp 
    ; New = [A|Temp]   % plus the current element otherwise. 
    ). 
+1

Эта версия всегда преуспевает для любого списка. Предназначена? – false 2014-02-26 21:04:47

7

SWI-Prolog предлагает exclude/3 и другие такие мета-предикаты Ваша исходная задача может быть закодирован следующим образом:. пример

are_identical(X, Y) :- 
    X == Y. 

filterList(A, In, Out) :- 
    exclude(are_identical(A), In, Out). 

Использование:

?- filterList(A, [A, B, A, C, D, A], Out). 
Out = [B, C, D]. 
3

Там есть неотъемлемая проблема с функциями фильтра, которые используют успех или неудачу предиката в качестве критерия фильтрации: результирующая программа больше не является чистой монотонной программой. Таким образом, он теряет все свои декларативные свойства —, единственным значением, которое остается, является процедурной поэтапной интерпретацией.Вот чистая, овеществленная версия фильтрации с использованием if_/3:

tfilter(_CT_2, [], []). 
tfilter(CT_2, [E|Es], Fs0) :- 
    if_(call(CT_2,E), Fs0 = [E|Fs], Fs0 = Fs), 
    tfilter(CT_2, Es, Fs). 

Первым аргумент, таким образом, замыкание/продолжение, который будет получать дополнительные два аргумента: элемент и полученное значение истины.

=(X,X,true). 
=(X,Y,false) :- dif(X,Y). 

Теперь результаты остаются точными:

| ?- tfilter(=(X),[A,B],Xs). 
B = A, 
X = A, 
Xs = [A,A] ? ; 
X = A, 
Xs = [A], 
dif(A,B) ? ; 
X = B, 
Xs = [B], 
dif(B,A) ? ; 
Xs = [], 
dif(X,A), 
dif(X,B) ? ; 
no 

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

Недостатком этого подхода является то, что необходимо предоставить обновленные версии всех критериев.

0

Я получаю имаго страны // Obtengo лос adultos де ун Pais, Страна = Pais, Люди = Personas, Person = уна Сола Персона

habitants(USA, [juan, pedro, david]) 

adults(Adults, Country) :- 
    findall(Person, (habitants(Country,People), member(People, Person), adult(Person)), Adults) 

Это фильтр пролог // Аси эс un filter en prolog

 Смежные вопросы

  • Нет связанных вопросов^_^