1

番号付きリストから最初の 3 つの要素を切り取り、結果を出力する Prolog 述語を作成しています。番号付きリストの例:

[e(f,1),e(o,2),e(o,3),e(b,4),e(a,5),e(r,6)].

通常のリストの元の述語は次のようになります。

strim([H|T],R) :-   
   append(P,R,[H|T]),  
   length(P,3).

したがって、長さの述語は番号付きリストに対しても完全に機能するため、ある番号付きリストを別の番号付きリストに追加する述語を記述するだけで済みました。

compose([],L,[L]).
compose([e(F,C)|T],e(A,_),[e(F,C)|L]) :-
   N is C+1,
   compose(T,e(A,N),L).

napp(X,[],X).
napp(L,[e(X,Y)|T],M):-
   compose(L,e(X,Y),L1),
   napp(L1,T,M).

番号付きリストの述語は、通常のリストの述語を少し変更したバージョンになると予想していたので、次のように書きました。

numstrim([e(X,Y)|T],R) :-
   napp(P,R,[e(X,Y)|T]),
   length(P,3).

ただし、次のエラーが発生します。

ERROR: compose/3: Arguments are not sufficiently instantiated

誰かがエラーの原因とそれを回避する方法を説明してもらえますか? 私はプロローグが初めてです。

4

1 に答える 1

2

インスタンス化エラーは、モディファイされた述語を使用する Prolog プログラムで一般的な現象です。これらは、特別な状況でのみ使用できる述語であり、たとえば、いくつかの引数が完全にインスタンス化されている必要があります。

初心者として、目標の順序を自由に交換でき、手続き上の制限を考慮する必要がないように、より一般的な述語を使用することをお勧めします。コードを自由に試してください。

たとえば、あなたの場合、次の簡単な変更によりcompose/3、すべての方向で機能する述語が得られます。

compose([], L, [L])。
compose([e(F,C)|T], e(A,_), [e(F,C)|L]) :-
        N #= C+1、
        compose(T, e(A,N), L)。

ここでは、修飾された述語を CLP(FD) 制約に単純に置き換えましたこれ(is)/2 (#=)/2整数よりも低レベルの述語を完全に包含しています。

この小さな変更の後 (Prolog システムによっては、より一般的な算術述語を使用するためにライブラリをインポートする必要がある場合があります)、次のようになります。

?- numstrim([e(f,1),e(o,2),e(o,3),e(b,4),e(a,5),e(r,6)], Es) .
不始末

したがって、インスタンス化エラーが実際には手続き的にしか理解できない別の問題を覆い隠しており、それが明らかになったことがわかります。

これを改善するために、次の 2 つの目標を好転させますnumstrim/2

numstrim([e(X,Y)|T], R) :-
        長さ(P, 3),
        napp(P, R, [e(X,Y)|T])。

これは、length(P, 3) 常に終了するためであり、常に最初に終了するゴールを置くことで、純粋で単調な論理プログラムの終了特性がせいぜい改善され、悪化することはありません。

したがって、次のようになります。

?- numstrim([e(f,1),e(o,2),e(o,3),e(b,4),e(a,5),e(r,6)], Es) .
Es = [e(b, _1442), e(a, _2678), e(r, _4286)] .

つまり、少なくとも今答えが得られます!

ただし、次のようになるため、述語はまだ普遍的に終了しません

?- numstrim([e(f,1),e(o,2),e(o,3),e(b,4),e(a,5),e(r,6)], Es) 、不始末

演習としてこれを修正します。

于 2016-10-28T08:45:24.880 に答える