您用於電路板的模式匹配不完整。 [(h1,t1)]
模式將只有匹配板與一個元素(一對(h1,t1)
)。
這與使用圖案(h1,t1):[]
相同,即。包含元素(h1,t1)
後跟空列表[]
的列表(:
)。
如果我們試圖用你給,(2,3)
和[(3,4), (5,6)]
實例運行代碼(注意:您需要的列表元素之間的逗號!),我們將得到以下內容:
goesP (2,3) [(3,4), (5,6)] LeftEnd
哈斯克爾將嘗試將這些論點與自定義中的模式從上到下進行匹配。與2
goesP (h,t) [(h1,t1)] LeftEnd
的第一和第三個參數匹配,通過「統一」 h
,t
與3
和LeftEnd
與LeftEnd
,但第二個將不匹配:
它會檢查以下模式第一。參數[(3,4), (5,6)]
對於列表(3,4):(5,6):[]
是'語法糖',而[(h1,t1)]
是對於列表(h1,t1):[]
的句法糖。我們可以統一h1
與3
和t1
與4
,但沒有什麼可以統一(5,6)
與。
哈斯克爾將移動到下一個可能性:
goesP (h,t) [(h1,t1)] RightEnd
的第一個參數匹配(與h
爲2
和t
爲3
),但第二個參數將失敗出於同樣的原因如前項。第三個參數也將無法匹配,因爲LeftEnd
和RightEnd
是不同的值(但這就是要點;))。
Haskell然後會看到沒有更多的可能性,所以程序會崩潰。
要解決此問題,您需要更改第二個參數的模式,以便正確處理具有多個Domino的Board。
爲LeftEnd
的情況下是很容易的,只是一個元素(h1,t1):[]
列表更改爲至少一個元素(h1,t1):_
(我還添加了額外的=
otherwise
後)的列表:
goesP (h,t) ((h1,t1):_) LeftEnd
| h==h1 || t==h1 = True
| otherwise = False
的RightEnd
的情況比較困難,因爲我們想要與最近的元素進行比較,但我們只能訪問的第一個。在這種情況下,我們可以保持你的定義檢查單元素列表,但也添加另一個使用遞歸的定義:如果列表中有多個元素,刪除第一個元素並再次檢查。這樣一來,任何非空目錄將最終被打破,直到它只有一個元素,它現有的模式可以工作(同樣,我添加了一個失蹤=
):
goesP (h,t) [(h1,t1)] RightEnd
| h==h1 || t==h1 = True
| otherwise = False
goesP (h, t) (_:xs) RightEnd = goesP (h, t) xs RightEnd
現在哈斯克爾將匹配[(3,4), (5,6)]
(這是糖的(3,4):(5,6):[]
)對(h1,t1):[]
。這將失敗,因爲列表的長度不同。然後它將匹配[(3,4), (5,6)]
對_:xs
,這將成功,統一xs
與(5,6):[]
。然後我們再次運行該功能,使用xs
。這一次(5:6):[]
將與(h1,t1):[]
統一,所以我們可以檢查數字是否相等。
此外,觀察:goesP
實際上過於複雜。您正在使用「花樣警衛」在值True
和值False
之間進行選擇;然而,花紋警衛要求 a Bool
與之合作。換句話說,這樣的代碼:
| h==h1 || t==h1 = True
| otherwise = False
可以理解爲說「創建Bool
值h==h1 || t==h1
;如果是True
,然後返回True
如果是False
然後返回False
。」
這顯然是多餘的:我們可以只返回值h==h1 || t==h1
:
goesP (h,t) ((h1,t1):_) LeftEnd = h==h1 || t==h1
goesP (h,t) [(h1,t1)] RightEnd = h==h1 || t==h1
goesP (h, t) (_:xs) RightEnd = goesP (h, t) xs RightEnd
更新:修正了我的RightEnd代碼
請格式化的,你提供的代碼片段(它看起來應該'喜歡this' )。目前,這幾乎是不可讀的。您可以使用反引號或四個縮進空格來獲得此效果。谷歌的「降價」,以瞭解更多關於它的語法規則。 – 2014-10-19 23:04:01
@AndrewThaddeusMartin編輯時只需點擊'help'按鈕,就會顯示所有的格式化語法。 – bheklilr 2014-10-19 23:05:07
此外,我們更喜歡在本網站上正確的語法和拼寫。我現在編輯了這篇文章,但是請確保你自己爲將來的問題做好準備。至於這一點,目前還不清楚你在談論什麼,「結局是左還是右」。 – leftaroundabout 2014-10-19 23:10:57