簡體   English   中英

如何檢查兩個列表是否部分相同的Haskell

[英]How to check if two lists are partially identical haskell

這是我的代碼,我試圖檢查一個列表是否可以與另一個列表完全相同。 這是一個多米諾骨牌游戲,一個Domino=(Int,Int)和一個Board = [Domino] ,終點是左或右。 我要檢查是否有多米諾骨牌進入棋盤,例如可以將多米諾骨牌(2,3)進入棋盤[(3,4)(5,6)]應該能夠到達左端,因為(2,3)(3,4)具有相似的元素。 這是我的代碼

goesP :: Domino -> Board -> End -> Bool

goesP (h,t) [(h1,t1)] LeftEnd
      | h==h1 || t==h1 =True
      | otherwise False
goesP (h,t) [(h1,t1)] RightEnd
      | h==t1 || t==t1 = True 
      | otherwise False

您用於電路板的圖案匹配不完整。 [(h1,t1)]模式將匹配具有一個元素(一對(h1,t1) )的Board。

這與使用模式(h1,t1):[] ,即。 列表( : )含有元素(h1,t1)隨后空列表[]

如果我們嘗試使用您提供的示例(2,3)[(3,4), (5,6)]來運行代碼(請注意:列表元素之間需要逗號!),我們將獲得以下內容:

goesP (2,3) [(3,4), (5,6)] LeftEnd

Haskell將嘗試將這些參數與您定義中的模式從上到下進行匹配。

它將首先檢查以下模式:

goesP (h,t) [(h1,t1)] LeftEnd

第一個和第三個參數將匹配,通過將h2統一,將t3 LeftEnd ,將LeftEndLeftEnd ,但是第二個參數將不匹配。 參數[(3,4), (5,6)]是列表(3,4):(5,6):[] '語法糖',而模式[(h1,t1)]是句法的列表(h1,t1):[]糖。 我們可以用3統一h1 ,用4統一t1 ,但是沒有什么可以統一(5,6)

Haskell將繼續進行下一個可能性:

goesP (h,t) [(h1,t1)] RightEnd

第一個參數將匹配( h2t3 ),但是第二個參數由於與上一個子句相同的原因而失敗。 第三個參數也將不匹配,因為LeftEndRightEnd是不同的值(但這就是要點;))。

然后,Haskell將看到沒有更多可能性,因此該程序將崩潰。

要解決此問題,您需要更改第二個參數的模式,以便正確處理具有多個Domino的Board。

LeftEnd情況非常簡單,只需將一個元素(h1,t1):[]的列表更改為至少一個元素(h1,t1):_otherwise我還添加了extra = ):

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

現在Haskell將[(3,4), (5,6)](3,4):(5,6):[]糖與(h1,t1):[]匹配(h1,t1):[] 這將失敗,因為列表的長度不同。 然后它將[(3,4), (5,6)]_:xs匹配,這將成功,將xs(5,6):[]統一。 然后,我們使用xs再次運行該函數。 這次(5:6):[] (h1,t1):[]統一,因此我們可以檢查數字是否相等。

另外,觀察到: goesP實際上過於復雜。 您正在使用“模式衛士”在值TrueFalse之間進行選擇; 但是,圖案后衛也需要 Bool配合使用。 換句話說,像這樣的代碼:

| h==h1 || t==h1 = True
| otherwise      = False

可以理解為“創建Boolh==h1 || t==h1 ;如果為True ,則返回True 。如果為False則返回False 。”

顯然,這是多余的:我們只需返回值h==h1 || t==h1 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代碼

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM