Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can Haskell Data Declarations Be Bounded By Type Values

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?

like image 418
Tanaki Avatar asked May 03 '13 15:05

Tanaki


1 Answers

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.

like image 94
C. A. McCann Avatar answered Sep 29 '22 11:09

C. A. McCann