2016-09-11 2 views
1

ich einen Datentyp wie dieses:Dynamisch Get Liste der Daten Konstrukteurs von Typ

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

In einem Test, möchte ich dynamisch die Konstrukteure alle extrahieren, eine Instanz von jedem Konstruktor machen, dann laufen der Test.

Ich habe durch Data.Typeable und Data.Data gesucht, aber ich habe noch nicht genau gesehen, wie man das nur mit dem Typ (ABC) beginnt.

Hilfe wird sehr geschätzt.

+0

Führt ['Arbitrary'] (https://hackage.haskell.org/package/QuickCheck-2.9.1/docs/Test-QuickCheck-Arbitrary.html) bereits das aus, was Sie wollen (ohne auf Daten zu setzen). Daten')? Welche Argumente würden Sie sonst den Konstrukteuren geben? – Alec

+0

Grundsätzlich möchte ich eine Liste von Zahlen mit der Liste der Konstruktoren verbinden. Aber ich möchte die Liste der Konstruktoren dynamisch abrufen. – kurzweil4

+0

'Arbitrary' hilft mir in diesem Fall nicht. Ich möchte nicht zufällig Daten generieren. Ich möchte eine Bedingung für jede Dateninstanz testen. – kurzweil4

Antwort

3

Wenn Sie mit Data.Data in Ordnung sind, funktioniert es für diesen Anwendungsfall, ist aber ein wenig klobig wegen der Int Parameter.

{-# 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 

Dann haben wir z.B.

λ 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] 

Wenn Sie nicht Data.Data verwenden möchten, Sie könnten in der Lage sein, dies zu tun mit GHC.Genertcs und -XDefaultSignatures


FWIW, würden Sie nicht mit irgendetwas davon zu tun haben, wenn Sie konnte ABC Refactoring, so dass die A, B, C-Tags ihre eigene Art ...

waren
data ABCTagged = ABCTagged ABC Int deriving Show 

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

... dann nur enumFrom minBound :: [ABC] verwenden, um die gesamte Liste zu bekommen. Einfach! Nicht sicher, wie machbar das für dich ist.

+0

Der Datentyp ist nicht mein tatsächlicher Datentyp. Es war das einfachste Beispiel, das ich formulieren konnte und das ausdrücken würde, was ich erreichen möchte. Das markierte Beispiel würde also nicht für mich funktionieren. Aber danke für den Vorschlag. – kurzweil4

+0

Ich zerlege Stück um Stück Ihre Antwort um meines eigenen Verständnisses willen, und wenn ich dieses 'fromConstrM (nur 10 :: Maybe Int) ctor 'ausführe, bekomme ich' Konnte den Typ' d 'nicht mit' Int 'vergleichen 'd' ist eine Variable des starren Typs, die durch eine Art verbunden wird, die durch den Kontext erwartet wird: forall d. Daten d => Vielleicht d bei : 52: 1 Voraussichtlicher Typ: Vielleicht d Tatsächlicher Typ: Vielleicht Int' In diesem Fall hält ctorA tatsächlich einen gültigen 'A'-Konstruktor 'show ctorA' ->" A " – kurzweil4

+0

OK, ich habe es teilweise herausgefunden: 'let c = cast 10 :: forall d. Daten d => Vielleicht d' dann 'fromConstrM c ctorA', aber ich bekomme' Just() ' – kurzweil4

Verwandte Themen