You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Haskell:如何统计棋盘上指定颜色(忽略数值)的棋子数量?

问题描述

我定义了以下Haskell数据类型:

data Player = Black | White deriving Show
data Cell = Piece Player Int | Empty deriving Show
type Board = [[Cell]]

以及如下Eq实例:

instance Eq Player where
  (==) Black Black = True
  (==) White White = True
  (==) _ _ = False

我希望统计当前棋盘(Board)上黑方(Black)棋子的数量。我知道若要查找特定棋子(如Piece Black 170)可使用如下代码:

getSpecificPiece :: Board -> [Player]
getSpecificPiece b = concat (map (filter (== Piece Black 170)) b)

但我想忽略棋子的数值(Int),仅查找黑方(Black)的棋子,尝试了concat (map (filter (== Piece Black _ )) b)却无法正常工作,请问该如何实现?

解决方案

你不能直接用== Piece Black _的原因是:_是模式匹配中的通配符,不能用来构造一个“模糊”的值参与相等性比较——==要求两边都是确定的表达式,而Piece Black _不是合法的表达式。

要实现忽略数值统计黑方棋子,有几种简洁的方式:

方法1:定义辅助判断函数

先写一个函数判断某个Cell是否是黑方棋子:

isBlackPiece :: Cell -> Bool
isBlackPiece (Piece Black _) = True  -- 匹配任意数值的黑棋
isBlackPiece _ = False               -- 其他情况(白棋或空单元格)都返回False

然后利用这个函数过滤棋盘并统计数量:

countBlackPieces :: Board -> Int
countBlackPieces = length . concatMap (filter isBlackPiece)

这里concatMap等价于concat . map,用来把二维的Board摊平成一维的Cell列表,再过滤出黑棋,最后用length得到数量。

方法2:用Lambda表达式直接过滤

如果不想单独定义辅助函数,可以在filter里直接写模式匹配的lambda:

countBlackPieces :: Board -> Int
countBlackPieces board = length $ concatMap (filter (\cell -> case cell of
                                                               Piece Black _ -> True
                                                               _ -> False)) board

方法3:列表推导式

用列表推导式的模式匹配特性,直接收集所有黑棋对应的占位符,最后取长度:

countBlackPieces :: Board -> Int
countBlackPieces board = length [() | row <- board, Piece Black _ <- row]

这里Piece Black _ <- row会自动过滤出当前行中的黑棋,每匹配到一个就生成一个(),最后列表的长度就是黑棋总数。

另外补充:你之前写的getSpecificPiece函数类型标注有错误——filter (== Piece Black 170)得到的是[Cell],concat之后还是[Cell],但你标注的返回类型是[Player],如果需要提取Player的话,应该改成:

getSpecificPiece :: Board -> [Player]
getSpecificPiece b = [p | row <- b, Piece p 170 <- row]

内容的提问来源于stack exchange,提问作者tdeus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 09:01:35