2012-08-07 25 views
1

我剛剛開始嘗試使用Prolog,並試圖編寫規則以確定列表是否僅包含唯一元素。我通過否定正面測試得到了它的第二個變體(但是我完全不明白爲什麼第一個變體不起作用)。否定和測試Prolog中的獨特集合

鑑於此文件:

uniqueElements([X|Y]) :- 
    notmember(X, Y), 
    uniqueElements(Y). 

notmember(X, Y) :- 
    \+ member(X, Y). 

hasRepeatedElements([X|Y]) :- 
    (
     member(X, Y) -> 
     true 
    ; hasRepeatedElements(Y) 
    ). 

uniqueElements_2(X) :- 
    \+ hasRepeatedElements(X). 

的GNU Prolog的解釋給出了這些反應:

| ?- uniqueElements([1,2,3]). 

no 
| ?- uniqueElements([1,2,3,2,3]). 

no 

| ?- uniqueElements_2([1,2,3]). 

yes 
| ?- uniqueElements_2([1,2,3,2,3]). 

no 

爲什麼是第一個響應 '不'? (我會希望成員返回false,被否定爲true,並且因此不會在uniqueElements的每次迭代中返回true)。我想我期待'\ +'表現得像'!'在C if子句中執行,或者在Python中執行「not」關鍵字。這是一個誤解嗎?

+0

您不測試空列表[]。 – joel76 2012-08-08 07:23:25

回答

1

uniqueElements,你沒有提供的基本情況進行遞歸:

uniqueElements([]). 

沒有這些條款,當一個特定的調用鏈得到的空單的情況下,它沒有找到任何適用的條款,這意味着在Prolog中fail。含義,「無法證明」。所以,你的電話uniqueElements([1,2,3])已經產生了相當於true && true && true && false

現在它應該工作。

hasRepeatedElements沒有爲基本情況定義的子句,但它無法找到空列表[]中是否有重複的元素與其語義一致 - 它應該已經發現沒有重複的元素首先是空列表。

在序言中,「不」意思是「不能證明......」。