2016-09-11 52 views
1

獲取數據構造的名單我有一個這樣的數據類型:動態地從類型

data ABCS = A Int | B Int | ... | Z Int deriving (Data, Typeable)

在測試中,我要動態提取所有構造函數,每個構造做一個實例,然後運行考試。

我一直在尋找通過Data.TypeableData.Data,但我還沒有看到/明白如何做到這一點,只有類型(ABC)開始。

非常感謝幫助。

+0

['Arbitrary'](https://hackage.haskell.org/package/QuickCheck-2.9.1/docs/Test-QuickCheck-Arbitrary.html)是否已經做到了你想要的(不訴諸於'數據。 Data')?否則,你想給構造函數提供什麼參數? – Alec

+0

基本上我想用構造函數列表連接數字列表。但我想動態獲取構造函數列表。 – kurzweil4

+0

'Arbitrary'在這種情況下不能幫助我。我不想隨機生成數據。我想測試每個數據實例的條件。 – kurzweil4

回答

3

如果您可以使用Data.Data,它適用於此用例,但由於參數Int有點笨重。

{-# LANGUAGE ScopedTypeVariables #-} 
import Data.Data 
import Data.Typeable 

allCtors :: forall a. Data a => [Int -> a] 
allCtors = map observeCtor $ dataTypeConstrs $ dataTypeOf (undefined :: a) 
    where 
    observeCtor :: Constr -> Int -> a 
    observeCtor c i = fromJust $ fromConstrM (cast i) c 

然後,例如,

λ data ABC = A Int | B Int | C Int deriving (Show, Data, Typeable) 
data ABC = A Int | B Int | C Int 
λ map ($ 2) allCtors :: [ABC] 
[A 2,B 2,C 2] 

如果你不想使用Data.Data,你可能能夠與GHC.Genertcs-XDefaultSignatures


FWIW要做到這一點,你就不必處理是否有任何這你可以重構ABC從而使A,B,C標籤是他們自己的類型......

data ABCTagged = ABCTagged ABC Int deriving Show 

data ABC = A | B | C deriving (Show, Eq, Ord, Enum. Bounded) 

...那麼就使用enumFrom minBound :: [ABC]讓整個列表。簡單!不知道這對你有多可行。

+0

數據類型不是我的實際數據類型。這是我能做出的最簡單的例子,可以表達我正在努力完成的事情。所以,標記的例子不適合我。但謝謝你的建議。 – kurzweil4

+0

爲了我自己的理解,我逐個分解你的答案,當我執行這個'fromConstrM(Just 10 :: Maybe Int)ctor'我得到了'無法將類型'd'與'Int' 'd'是一個剛性類型變量,由 綁定,上下文預期類型: forall d。 Data d => Maybe d at :52:1 預期類型:也許d 實際類型:Maybe Int'在這種情況下,ctorA的確擁有一個有效的'A'構造函數'show ctorA' - >「A」 – kurzweil4

+0

好的,我已經部分想到了:'讓c = cast 10 :: forall d。數據d =>也許d'然後'fromConstrM c ctorA',但我得到'只是()' – kurzweil4