Can Haskell Data Declarations Be Bounded By Type Values

declaration, functional-programming, haskell, types

Solution

The simplest way to do something similar is to parameterize the `Checker` type with what's called a "phantom type":

data Black
data White

Note that neither of these have any values. They only exist to indicate what color a `Checker` is.

data Checker a = Checker Int

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

By the way, you don't need those parentheses in the `GameBoard` declaration.

The downside to this approach is that the two colors are now different types, meaning you can't write a function that takes, say, a list of checkers of multiple colors, only a single color.

You could make the phantom types a bit more concrete in order to track allowed colors:

data Black = Black
data White = White

data Checker a = Checker a Int

type AnyChecker = Checker (Either Black White) 

But this can quickly become a lot of hassle to use.

What I suspect you really want is a way to restrict the range of values allowed in one context without making it a completely different type in all contexts. Unfortunately, this isn't really possible in any straightforward fashion in Haskell.

It's a reasonable idea, and some languages do have similar features. Supporting distinctions like this in a generalized way is not simple to add to Haskell's existing type system without collateral damage, though, such as making type inference less robust, even in code not using such a feature.

Problem

In Haskell, is there a way to limit a data type by the value of its components? I've drafted an example. Say you have a checkers game. A checker is either of the Black or White type. ``` data CheckerType = BlackChecker | WhiteChecker deriving (Eq) data Checker = Checker CheckerType Int ``` The game board for a checker game contains a set of Black checkers and White checkers. ``` data GameBoard = GameBoard ([Checker]) ([Checker]) ``` In the previous declaration, is there any way to enforce the Checkers in the first [Checker] to be of CheckerType black, and the second to be of the opposing type?

Original source

Related problems