2012-07-02 7 views
5

Nel mio programma Haskell Ho un ADT con molti costruttori:Come determinare il costruttore di dati da un codice esterno?

data MyData = Con1 | 
    Con2 | 
    ... 
    Con20 

devo una funzione foreign export ccall, che avvolge [MyData] in una matrice di StablePtr's. Dopo averlo chiamato ho bisogno di determinare quale costruttore è stato usato per costruire ogni elemento.

Potrebbe essere risolto questo modo

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

ma poi ho dovrebbe definire manualmente queste costanti nell'intestazione C. Questo è soggetto a errori, quindi mi chiedo se c'è un modo per fare in modo che GHC faccia questo lavoro per me.

risposta

0

Ho trovato la soluzione per questo.

ho definito i possibili tipi enum costruttore come nel mio codice C:

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

Poi ho usato C->Haskell gancio enum nella mia fonte Haskell:

{#enum MyDataConstructor deriving (Show) #} 

Dopo la trasformazione di questa linea si rivolge a

data MyDataConstructor = MyDataCon1 
    | MyDataCon2 
    ... 
    | MyDataCon20 

Ora posso definire getType in questo modo:

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

derivante da Enum per il tipo Haskell ed esportazione fromEnumMyData :: MyData -> Int ; fromEnumMyData = fromEnum.

Quindi è possibile eseguire l'analisi del caso sul lato C osservando il tag Int che GHC assegna.

+0

Siamo spiacenti, non capisco. Come faccio a sapere a quale costruttore si riferisce qualche tag? – arrowd

+0

Non lo fai - è dato dall'ordinazione dell'enumerazione. Ma hai già perso tutte le informazioni sul lato C, quindi devi fare affidamento su una mappatura non sicura. –

+0

Quindi, non è possibile generare automaticamente quella mappatura? – arrowd