Haskell数据声明是否可以按类型值限制

Tan*_*aki 8 haskell types functional-programming declaration

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

data CheckerType = BlackChecker | WhiteChecker deriving (Eq)

data Checker = Checker CheckerType Int
Run Code Online (Sandbox Code Playgroud)

棋盘游戏的游戏板包含一组黑色棋子和白棋子.

data GameBoard = GameBoard ([Checker]) ([Checker])
Run Code Online (Sandbox Code Playgroud)

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

C. *_*ann 13

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

data Black
data White
Run Code Online (Sandbox Code Playgroud)

请注意,这些都没有任何值.它们仅用于表示a Checker是什么颜色.

data Checker a = Checker Int

data GameBoard = GameBoard [Checker Black] [Checker White]
Run Code Online (Sandbox Code Playgroud)

顺便说一下,你在GameBoard声明中不需要那些括号.

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

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

data Black = Black
data White = White

data Checker a = Checker a Int

type AnyChecker = Checker (Either Black White) 
Run Code Online (Sandbox Code Playgroud)

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

我怀疑你真正想要的是一种方法来限制一个上下文中允许的值的范围,而不是在所有上下文中使它成为完全不同的类型.不幸的是,在Haskell中,这在任何简单的方式中都不可能实现.

这是一个合理的想法,有些语言也有类似的功能.以通用的方式支持这样的区别并不是简单地添加到Haskell的现有类型系统而没有附带损害,但是,例如使类型推断不那么健壮,即使在不使用这样的特征的代码中也是如此.

  • 如果您不想这样做,一个解决方法可能会坚持使用您的原始代码,但不要导出`GameBoard`构造函数.而是强制模块的用户调用适当分配检查器的自定义构造函数,并使用维护颜色分配的函数更新它. (7认同)