1

私はPrologのアイデアを学んでおり、これが私が実践したいことです:

私はこのように働くことができるPrologプログラムを書きたいです:

?- input([apple,is,fruit]).
?- input([chicken,is,meat]).
?- input([Is,apple,meat]).
No, it is a fruit
?- input[(Is,chicken,meat])
Yes.

そして、このプログラムを実装しようとしたときに、いくつかの問題が発生しました。

(1)入力を読み取り、質問とアサーションを区別するためにこのコードを使用しましたが、失敗します:

input([]).
input([X|R]) :- X is 'Is', write('test code read question'); write("test code read assertion").

(2)入力メッセージから有用な情報を除外する方法についてはまだ混乱しています。たとえば、[Apple,is,fruit]入力配列では、必要なのはapplefruitです。is単語をジャンプするために通常どのように行いますか?

私はプログラムにあまりにも多くのものをハードコーディングしたくありません、そして私がそれから学ぶのを助けることができる問題を解決するために良い関数型プログラミングスタイルを好みます。

前もって感謝します。

4

2 に答える 2

6

それらを楽しんでいるという理由だけで、私は定節文法 (DCG) に傾倒するでしょう。次に、ステートメントを作成して、かなり簡単に解析できます。

word(Word) --> [Word].
statement(Statement) --> 
    word(Thing), [is], word(Category), 
    { Statement =.. [Category, Thing] }.

ここで DCG で行われているトリックは、文法が差分リスト表現に変換されていることです。括弧内の部分は通常の Prolog コードです。その前後の部分は、リストのリテラル部分または他の文法規則として解釈されます。したがって、[単語] は 1 つのアトムに一致します。実際には、次のようにルールを記述できます。

statement(Statement) -->
    [Thing, is, Category],
    { Statement =.. [Category, Thing] }.

同じ効果があり、おそらくもっと読みやすくなりますが、私は衒学的であることが好きです。=..リストをファクトに、またはその逆に変換する の使用に特に注意してください(したがって、[fruit, apple]になりますfruit(apple))。

DCG を使用した解析は非常に簡単です。次を使用しますphrase/2

?- phrase(statement(X), [apple,is,fruit]).
X = fruit(apple).

asserta次に、これらの句を動的ストアに挿入するために使用できます。

input(Text) :- 
    phrase(statement(Statement), Text),
    asserta(Statement).

例えば:

?- input([apple,is,fruit]).
true.

?- fruit(X).
X = apple.

これで、クエリを解析するための別の句を作成できます。

query(Query) --> 
    ['Is'], word(Word), word(Category), 
    { Query =.. [Category, Word] }.

とても似ています!繰り返しますが、必要に応じて、次の構文を使用できます。

query(Query) -->
    ['Is', Word, Category],
    { Query =.. [Category, Word] }.

ここで、両方の文法規則を 1 つの "文" 規則に結合する句を書きたいと思うかもしれません:

sentence(statement(S)) --> statement(S).
sentence(query(Q))     --> query(Q).

やってみて:

?- phrase(sentence(X), ['Is', apple, fruit]).
X = query(fruit(apple)).

?- phrase(sentence(X), [apple, 'is', fruit]).
X = statement(fruit(apple)) ;

解析されたファクトだけでなく、それがステートメントであるかクエリであるかを示すラッパーも取得することがわかります。ステートメントとクエリの代わりにこれを使用して解析し、次のinputように書き換えることができるようになりました。

input(Text) :-
    phrase(sentence(S), Text), perform(S).

作業を処理するための補助を追加しました:

perform(statement(S)) :- asserta(S).
perform(query(Q))     :- Q.

これは、後で文法の抽象化を追加するときに便利です。各perform句は異なる「文」タイプを処理するため、上記の解析を行い、以下の作業を処理します。そして今、多かれ少なかれ、あなたが望んでいたものを手に入れました:

?- input([apple,is,fruit]).
true ;
false.

?- input(['Is',apple,fruit]).
true.

?- input(['Is',banana,fruit]).
false.

ルールにカットを導入し、特別な出力で true/false を処理することで改善できますsentenceが、特に将来的に異なる構文を処理できるようにしたい場合は、これが私が行きたい方向だと思います。

于 2012-10-04T19:23:02.943 に答える
1

Prolog構文を使用していません。あなたが説明することは、このように実装することができます(テストされていないコード):

:- dynamic facts/1.

input(L) :-
  (  L == [is|_]
  -> (  facts(L)
     -> true
     ;  get_kind(L, K), format('no, it is ~w~n', [K])
     )
  ;  assert(facts(L))  % should check duplicates?
  ).

get_kind([is, Object, _], Kind) :-
  facts([Object, is, Kind]) -> true ; Kind = unknow.

大文字で始まる記号に注意してください。これらは変数であり、アトムではありません。

于 2012-10-04T19:08:04.170 に答える