8

在 Haskell 中,有没有办法通过其组件的值来限制数据类型?我已经起草了一个例子。假设你有一个跳棋游戏。检查器是黑色或白色类型的。

data CheckerType = BlackChecker | WhiteChecker deriving (Eq)

data Checker = Checker CheckerType Int

棋盘游戏的棋盘包含一组黑棋和白棋。

data GameBoard = GameBoard ([Checker]) ([Checker])

在前面的声明中,有没有办法强制第一个 [Checker] 中的 Checker 为黑色 CheckerType,而第二个为相反类型?

4

1 回答 1

13

做类似事情的最简单方法是Checker使用所谓的“幻像类型”参数化类型:

data Black
data White

请注意,这些都没有任何值。它们的存在只是为了表明 a 是什么颜色Checker

data Checker a = Checker Int

data GameBoard = GameBoard [Checker Black] [Checker White]

GameBoard顺便说一句,声明中不需要这些括号。

这种方法的缺点是这两种颜色现在是不同的类型,这意味着你不能编写一个函数,例如,一个包含多种颜色的检查器列表,只有一种颜色。

您可以使幻像类型更具体一些,以便跟踪允许的颜色:

data Black = Black
data White = White

data Checker a = Checker a Int

type AnyChecker = Checker (Either Black White) 

但这很快就会变得很麻烦。

我怀疑您真正想要的是一种方法来限制在一个上下文中允许的值范围,而不会在所有上下文中使其成为完全不同的类型。不幸的是,这在 Haskell 中不可能以任何直接的方式实现。

这是一个合理的想法,并且某些语言确实具有类似的功能。但是,以一种通用的方式支持这样的区别并不容易添加到 Haskell 的现有类型系统中而不会造成附带损害,例如使类型推断不那么健壮,即使在不使用此类功能的代码中也是如此。

于 2013-05-03T16:16:01.983 回答