2013-08-18 20 views
11

Diciamo che abbiamoHaskell: ottenere il nome del costruttore di dati come stringa

data D = X Int | Y Int Int | Z String 

Vorrei avere una funzione getDConst

getDConst :: D -> String 

che restituisce "X", "Y", o " Z ", secondo il costruttore di dati utilizzato per il suo input. C'è un modo generico per scrivere questo senza dover fare case su ogni costruttore di dati? (Io sono ok con soluzioni basandosi su Data.Typeable o qualcosa di simile)

risposta

13

trovato la soluzione io stesso, ma lasciando a questa domanda per aiutare gli altri:

import Data.Data 
data D = X Int | Y Int Int deriving (Data,Typeable) 

let result = show $ toConstr (X 3) -- result contains what we wanted 
+1

Se qualcun altro ottiene anche un errore con questo: Prova ad aggiungere '{- # LINGUA DeriveDataTypeable # -}' per l'inizio del file. È necessario in GHC quando si derivano dati e tipizzabili. – jPlatte

6

Se non si desidera utilizzare Typeable, è anche possibile fai questo con Show.

getDConst :: D -> String 
getDConst = head . words . show 

Show non sarà in uscita tutti i campi, perché è pigro. È possibile verificare che runing questo codice in ghci:

Prelude> data D = D [Int] deriving (Show) 
Prelude> getDConst $ D [1..] 
"D" 
+0

Si potrebbe anche voler implementare un output di show personalizzato che non coinvolga il costruttore. – kqr

+0

'show' è pigro, quindi probabilmente non sarà molto lento. Si noti come 'take 5 (show (Just undefined))' funzioni correttamente. –

+2

Vuoi dire 'parole', non' unwords'. (In realtà, scriverei qualcosa come 'takeWhile (/ = ''.. Show') – Lynn

Problemi correlati