由於newtype
和GeneralizedNewtypeDeriving
擴展,可以定義不同的輕巧類型很少的努力:如何「newtype」IntSet?
newtype PersonId = PersonId Int deriving (Eq, Ord, Show, NFData, ...)
newtype GroupId = GroupId Int deriving (Eq, Ord, Show, NFData, ...)
允許類型系統,以確保一個PersonId
不使用其中一個GroupId
預期的事故,但仍然從Int
繼承選定的類型實例。
現在,人們可以簡單地定義PersonIdSet
和GroupIdSet
作爲
import Data.Set (Set)
import qualified Data.Set as Set
type PersonIdSet = Set PersonId
type GroupIdSet = Set GroupId
noGroups :: GroupIdSet
noGroups = Set.empty
-- should not type-check
foo = PersonId 123 `Set.member` noGroups
-- should type-check
bar = GroupId 123 `Set.member` noGroups
它的類型是安全的,因爲地圖是通過鑰匙式參數化,而且,在Set.member
操作是多態的,所以我並不需要定義每個ID型變體,如personIdSetMember
和groupIdSetMember
(和所有其他集合的操作我可能要使用)
...但我該如何使用更有效的IntSet
!而非爲PersonIdSet
和GroupIdSet
分別與上面的例子類似嗎?是否有一種簡單的方法,無需將整個Data.IntSet API作爲類型類包裝/複製?
IIRC no。但我想你可以使用模板Haskell。 – fuz 2011-04-21 16:04:56
你寫了評論說什麼應該輸入檢查,什麼不是。您是否嘗試編譯,結果與您預期的結果不同? – jmg 2011-04-21 16:05:59
@jmg,我只是試圖確定,結果如預期。 GHC發出的實際錯誤是'無法與實際類型'GroupId''匹配的預期類型'PersonId' – hvr 2011-04-21 19:53:25