プロローグ:リストのフィルタリング?
-
08-07-2019 - |
質問
現在、Prologで非常に短いプロジェクトに取り組んでいますが、「フィルター」を適用しようとして動けなくなりました。リストに作成しました。フィルターと呼べるものが用意されていますが、適用できません。私が説明する方が良いでしょう:
filter(A, B)
...特定の条件が満たされた場合、「true」を出力します。
filterList(A, [X, Y, Z])
...フィルターを出力する2番目の引数のすべての要素を含むリストを出力します false 。 (したがって、filter(A、X)がtrueの場合、出力は[Y、Z]になります。)
「フィルター」があります。関数の準備はできましたが、今度は2番目の例に示すようにリストに適用する必要があり、最初の引数を適用したときにフィルターがtrueを返すすべての要素を除外します。
したがって、フィルターが単純なA == Bである場合、関数はA [A、B、A、C、D、A]を受け取り、[B、C、D]を出力し、すべてのフィルターが適用される要素、明らかに。
関数の基本構造に問題があるため、このような関数の基本的なアウトラインを提供できる人がいれば、とても助かります。状況を可能な限り簡素化して、必要に応じて提供および変更できるものであれば何でも使用できるようにします。
事前に感謝します!
解決
Prologで高階関数を検索する場合は、 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
、 folder
、および compose
も定義しています。彼が言及している制限の多く(たとえば、 call / 3
の欠落や高次の apply
などは適用されないことに注意してください。SWI-Prologには = ..
演算子。彼の懸念すべてに対処し、任意のn次論理を可能にします。
他のヒント
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].
述語の成功または失敗をフィルタリングの基準とするフィルター関数には、固有の問題があります。結果のプログラムは、もはや純粋な単調なプログラムではありません。したがって、宣言的なプロパティはすべて失われます。残っている唯一の意味は、手順ごとの解釈です。以下は、 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).
したがって、最初の引数は、要素と結果の真理値という2つの引数をさらに受け取る閉包/継続です。
=(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
に等しいという基準によって2つの要素のリストをフィルタリングする方法は4つあります。各要素は等しい場合と異なる場合があります。
このアプローチの欠点は、すべての基準の具体化されたバージョンを提供する必要があることです。
さて、あなたは何を知っていましたか?だから、ここに私自身の質問への答えを提出する、予想通り、本当に短い関数が仕事をした:
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人
habitants(USA, [juan, pedro, david])
adults(Adults, Country) :-
findall(Person, (habitants(Country,People), member(People, Person), adult(Person)), Adults)
これはプロローグのフィルターです//これはプロローグのフィルターです
filter(_,[],[]).
filter(Predicate,[First|Rest],[First|Tail]) :-
filter(Predicate,Rest,Tail).
filter(Predicate,[_|Rest],Result) :-
filter(Predicate,Rest,Result).