2013-05-03 61 views
8

在Haskell中,有沒有一種方法可以通過組件的值來限制數據類型?我已經起草了一個例子。假設你有一個跳棋遊戲。檢查器是黑色或白色類型。Haskell數據聲明可以通過類型值進行限制

data CheckerType = BlackChecker | WhiteChecker deriving (Eq) 

data Checker = Checker CheckerType Int 

棋盤遊戲的遊戲板包含一組黑色跳棋和白色棋子。

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

在先前聲明,是沒有什麼辦法來執行跳棋在第一[檢測器]是CheckerType的黑色,而第二是相對的類型的?

+0

可能的重複[正整數類型](http://stackoverflow.com/questions/11910143/positive-integer-type) – dave4420 2013-05-03 16:11:17

回答

13

做類似的事情最簡單的方法是參數化類型Checker用什麼叫做「幻影類型」:

data Black 
data White 

注意,這些都不具有任何價值。它們只存在以指示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的現有類型系統中,而是沒有附帶損害,例如,即使在不使用這種功能的代碼中,也使得類型推斷更不穩健。

+7

如果你不想這樣做,一個解決方法可能會堅持你的原始代碼,但不要導出'GameBoard'構造函數。而是強制你的模塊的用戶調用一個自定義的構造函數來適當地分配檢查器,並使用維護顏色分配的函數來更新它。 – mhwombat 2013-05-03 17:42:46