Haskell中isCornerPos遇boardSize定义冲突,isCornerPos'正常,原因何在?
为什么
isCornerPos会出现boardSize定义冲突,而isCornerPos'不会? 这个问题的核心是Haskell模式匹配的变量绑定规则在搞鬼,我来给你拆解清楚:
问题根源
在Haskell的case表达式模式里,小写开头的标识符会被当作新的变量绑定,而不是引用你之前定义的全局常量boardSize。
你看isCornerPos里的这行:
(boardSize, boardSize) -> True
这里的boardSize并不是你全局定义的那个Int常量,而是两个新的局部变量——它们会匹配任意整数,把值绑定到boardSize这个名字上。这就和你全局已经定义的boardSize产生了名字冲突,编译器自然会报错说“定义冲突”。
而isCornerPos'里直接用字面量8就没有这个问题,因为字面量是固定值,不会被当作变量绑定,编译器只会检查输入是否等于8,不会创建新的变量。
解决办法
有几种方式可以修复这个问题,选你觉得顺手的就行:
1. 用守卫(Guard)代替模式匹配
守卫里可以直接引用全局常量,写法也很直观:
boardSize :: Int boardSize = 8 isCornerPos :: Position -> 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
2. 调整case表达式的写法,把常量判断移到右侧
如果坚持要用case,可以把对boardSize的判断放在箭头右边,避免在模式里用小写标识符:
isCornerPos :: Position -> Bool isCornerPos (i, j) = case (i, j) of (1, 1) -> True (1, j') -> j' == boardSize (i', 1) -> i' == boardSize (i', j') -> i' == boardSize && j' == boardSize _ -> False
3. 用模式同义词(进阶)
如果你经常需要在模式里用这个常量,可以启用PatternSynonyms扩展,把boardSize定义成一个模式:
{-# LANGUAGE PatternSynonyms #-} boardSize :: Int boardSize = 8 pattern BoardSize :: Int pattern BoardSize <- _ where BoardSize = boardSize isCornerPos :: Position -> Bool isCornerPos (i, j) = case (i, j) of (1, 1) -> True (1, BoardSize) -> True (BoardSize, 1) -> True (BoardSize, BoardSize) -> True _ -> False
这种方式比较适合需要多次复用常量模式的场景。
关键知识点回顾
Haskell的模式匹配规则:
- 小写开头的标识符:绑定新变量
- 大写开头的标识符:匹配构造器(比如
Just、Left) - 字面量(数字、字符串):匹配固定值
所以以后在模式里要引用常量的时候,记得要么用守卫,要么用模式同义词,别直接用小写的常量名哦!
内容的提问来源于stack exchange,提问作者Lo HaBuyshan
相关产品推荐
相关产品推荐

