2014-10-19 66 views
0

这是我的代码即时通讯尝试检查列表是否可以与其他列表相同。这是一个多米诺骨牌游戏,一个Domino=(Int,Int)和一个Board = [Domino]和结束左或右。我要检查是否有任何多米诺骨牌进入董事会说,例如多米诺骨牌(2,3)进入[(3,4)(5,6)]应该能够走到左端,因为(2,3)(3,4)有一个相似的元素。这是我的代码如何检查两个列表是否部分相同haskell

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 
+1

请格式化的,你提供的代码片段(它看起来应该'喜欢this' )。目前,这几乎是不可读的。您可以使用反引号或四个缩进空格来获得此效果。谷歌的“降价”,以了解更多关于它的语法规则。 – 2014-10-19 23:04:01

+2

@AndrewThaddeusMartin编辑时只需点击'help'按钮,就会显示所有的格式化语法。 – bheklilr 2014-10-19 23:05:07

+0

此外,我们更喜欢在本网站上正确的语法和拼写。我现在编辑了这篇文章,但是请确保你自己为将来的问题做好准备。至于这一点,目前还不清楚你在谈论什么,“结局是左还是右”。 – leftaroundabout 2014-10-19 23:10:57

回答

1

您用于电路板的模式匹配不完整。 [(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 

的第一和第三个参数匹配,通过“统一” ht3LeftEndLeftEnd,但第二个将不匹配:

它会检查以下模式第一。参数[(3,4), (5,6)]对于列表(3,4):(5,6):[]是'语法糖',而[(h1,t1)]是对于列表(h1,t1):[]的句法糖。我们可以统一h13t14,但没有什么可以统一(5,6)与。

哈斯克尔将移动到下一个可能性:

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

的第一个参数匹配(与h2t3),但第二个参数将失败出于同样的原因如前项。第三个参数也将无法匹配,因为LeftEndRightEnd是不同的值(但这就是要点;))。

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 

可以理解为说“创建Boolh==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代码