2013-05-03 15 views
8

Haskellでは、コンポーネントの値によってデータ型を制限する方法はありますか?私は例を起草しました。チェッカーゲームがあるとします。チェッカーは黒または白のいずれかのタイプです。Haskellのデータ宣言を型の値でバインドすることができます

data CheckerType = BlackChecker | WhiteChecker deriving (Eq) 

data Checker = Checker CheckerType Int 

チェッカーゲームのゲームボードには、ブラックチェッカーとホワイトチェッカーのセットが含まれています。前の宣言において

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

、最初の[チェッカー]でチェッカーを適用する方法はCheckerType黒色であることがあり、第二は、対向型ですか?これらのいずれも任意の値を持っていることを

data Black 
data White 

注:

+0

[正の整数型]の複製が可能です(http://stackoverflow.com/questions/11910143/positive-integer-type) – dave4420

答えて

13

似た何かをする最も簡単な方法は、「ファントムタイプ」と呼ばれるものでCheckerタイプをパラメータ化することです。それらは、Checkerの色を示すためだけに存在します。ところで

data Checker a = Checker Int 

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

、あなたはGameBoard宣言でこれらの括弧は必要ありません。

このアプローチの欠点は、2つの色が異なる種類になっていることです。つまり、複数の色のチェッカーのリストを1つの色しか持たない関数を書くことはできません。

あなたが許可された色を追跡するために、ファントムの種類がもう少し具体的な作ることができます:

data Black = Black 
data White = White 

data Checker a = Checker a Int 

type AnyChecker = Checker (Either Black White) 

をしかし、これはすぐに使用するには手間が多くなることができます。

あなたが本当に望んでいると思うのは、すべてのコンテキストで完全に異なるタイプにすることなく、あるコンテキストで許可される値の範囲を制限する方法です。残念ながら、これはハスケルでは単純ではありません。

これは合理的な考えであり、一部の言語にも同様の機能があります。一般化された方法でこのような区別をサポートすることは、タイプ推論をあまり強くしないなど、副作用のないHaskellの既存の型システムに追加するのは簡単ではありません。

+7

これをしたくない場合は、元のコードに固執する可能性があります'GameBoard'コンストラクタをエクスポートしません。代わりに、モジュールのユーザーにチェッカーを適切に割り当てるカスタムコンストラクターを呼び出し、色の割り当てを維持する関数を使用して更新するようにします。 – mhwombat

関連する問題