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