我在Conflicting definitions for 'boardSize'
但未isCornerPos
获得isCornerPos'
。为什么呢?
boardSize :: Int
boardSize = 8
isCornerPos :: Position -> Bool
isCornerPos (i, j) =
case (i, j) of
(1, 1) -> True
(1, boardSize) -> True
(boardSize, 1) -> True
(boardSize, boardSize) -> True -- problem with this line
_ -> False
isCornerPos' :: Position -> Bool
isCornerPos' (i, j) =
case (i, j) of
(1, 1) -> True
(1, 8) -> True
(8, 1) -> True
(8, 8) -> True
_ -> False
答案 0 :(得分:3)
->
左侧的名称是要匹配的模式,而不是要使用的变量。匹配模式时,文字只能匹配自身,但变量匹配任何,并且该值被赋予 变量。这意味着您的(1, boardSize) -> True
匹配第一个元素为1的任何元组,并将boardSize
设置为等于右侧大小的表达式中的第二个元素。
它与定义函数时的工作方式相同,其中isCornerPos (i,j) = ...
分别将参数元组的两个元素分配给i
和j
,而不是尝试匹配反对参数的现有值i
和j
。实际上,这与<{1}}表达式中的完全相同,因为函数定义使用语法糖代替case
匹配。
case
只是
的缩写isCornerPos (i,j) = ...
使用isCornerPos = \x -> case $x of
(i,j) -> ...
的标准方法是使用警卫:
boardSize
或者将它与模式匹配结合起来:
isCornerPos :: Postion -> Bool
isCornerPos (i,j) | i == 1 && j == 1 = True
| i == 1 && j == boardSize = True
| i == boardSize && j == 1 = True
| i == boardSize && j == BoardSize = True
| otherwise = False
我会定义一个辅助函数,并在没有警卫的情况下编写它。
isCornerPos :: Postion -> Bool
isCornerPos (1,1) = True
isCornerPos (1,j) = j == boardSize
isCornerPos (i,1) = i == boardSize
isCornerPos (i,j) = i == boardSize && j == boardSize
答案 1 :(得分:2)
模式匹配引入了 new 变量。您将boardSize
重新声明为本地新变量。请使用新的变量名称,并使用警卫将其约束为boardSize
。 E.g。
case (i, j) of
(1, 1) -> True
(1, y) | y == boardSize -> True
(x, 1) | x == boardSize -> True
(x, y) | x == boardSize && y == boardSize -> True
_ -> False
请注意,上面的代码可以大大改进。很多True
和False
提示使用&&
或||
代替。
作为提示,请尝试使用(some property of i) && (some property of j)
,如果您想简化代码。根据需要,属性可以包含==
和||
。 (对于更高级的解决方案,请利用elem
)