2012-07-02 5 views
5

In meinem Haskell Programm ich habe eine ADT mit vielen Konstrukteuren:Wie ermitteln Sie den Konstruktor der Daten aus Fremdcode?

data MyData = Con1 | 
    Con2 | 
    ... 
    Con20 

Ich habe eine foreign export ccall Funktion, die [MyData] in einem Array von StablePtr's wickelt. Nach dem Aufruf muss ich feststellen, welcher Konstruktor zum Aufbau jedes Elements verwendet wurde.

Es könnte auf diese Weise

foreign export ccall getType :: StablePtr MyData -> IO CInt 
getType (Con1) = return 1 
getType (Con2) = return 2 
... 

gelöst werden, aber dann würde ich manuell diese Konstanten in C-Header definieren müssen. Das ist fehleranfällig, also frage ich mich, ob es einen Weg gibt, GHC dazu zu bringen, diesen Job für mich zu erledigen.

Antwort

0

Ich habe eine Lösung dafür gefunden.

I definiert haben möglich Konstruktor Typen als Enum in meinem C-Code:

typedef enum 
{ 
    MyDataCon1, 
    MyDataCon2, 
    ... 
    MyDataCon20 
} MyDataConstructor; 

Dann habe ich C->Haskell Enum Haken in meine Haskell Quelle:

{#enum MyDataConstructor deriving (Show) #} 

Nachdem diese Linie Vorverarbeitung wendet sich an

data MyDataConstructor = MyDataCon1 
    | MyDataCon2 
    ... 
    | MyDataCon20 

Nun kann ich getType auf diese Weise definieren:

foreign export ccall getType :: StablePtr MyData -> IO CInt 
getType md = do 
    md' <- deRefStablePtr md 
    case md' of 
     Con1 -> return $ fromEnum MyDataCon1 
     Con2 -> return $ fromEnum MyDataCon2 
     ... 
     Con20 -> return $ fromEnum MyDataCon20 
5

Ableiten Enum für Ihren Haskell-Typ und exportieren fromEnumMyData :: MyData -> Int ; fromEnumMyData = fromEnum.

Dann können Sie eine Fallanalyse auf der C-Seite durchführen, indem Sie sich das Int-Tag ansehen, das GHC zuweist.

+0

Sorry, habe es nicht verstanden. Woher weiß ich, auf welchen Konstruktor ein Tag verweist? – arrowd

+0

Sie nicht - es ist durch die Aufzählung Reihenfolge gegeben. Aber Sie haben sowieso alle Informationen auf der C-Seite verloren, also müssen Sie sich auf ein unsicheres Mapping verlassen. –

+0

Es ist also nicht möglich, diese Zuordnung automatisch zu generieren? – arrowd

Verwandte Themen