2011-11-18 18 views
5

Sto provando a leggere nei file CSV dove la prima riga ha i nomi di ogni colonna. Devo quindi modificare questi file in modo appropriato. Ho un'idea di dove leggo prima il file e poi creo un nuovo tipo di dati chiamato Record, e quindi tutti i record successivi sono solo istanze di questo tipo, ora ovviamente se il programma ha solo a che fare con un tipo di file CSV con un certo numero di colonne sarebbe abbastanza facile, ma purtroppo non sarà sempre così.C'è un modo per creare un tipo di dati in Haskell con un numero indeterminato di campi

Quindi la mia domanda è si può fare qualcosa di simile a

createRecordClass (x:xs) = data Record {addRecord(x:xs)} 
addRecord (x:xs) = x::String, addRecord xs 

O sono solo parlando pazzo e sarebbe più facile solo per avere un elenco di rappresentare tutto ciò?

+0

Stai parlando pazzo –

+1

Non sono così familiare con il tuo problema, e questo può variare a seconda ... ma ti suggerisco di modellare le operazioni che puoi fare su questi file CSV in astratto, invece di provare a piegare loro nel programma. Una volta che hai un tipo di dati "magici" che corrisponde ai tuoi file CSV, devi avere funzioni "magiche" che si astraggono su di loro. Se il tuo tipo non è magico, non è necessario che le tue funzioni siano. – luqui

+2

Che cosa fai con questi file CSV? Quali tipi di dati possono contenere? Di quanta sicurezza di tipo hai bisogno qui? – hugomg

risposta

1

È possibile utilizzare Template Haskell per ottenere ciò che si desidera. Questa è una tecnica potente per generare il codice Haskell tramite Haskell (simile nell'intento alle macro in lisp).

Poiché hai menzionato che desideri l'intestazione del file csv per creare un tipo di dati personalizzato, devi leggere il file e quindi generare un tipo di dati in Template Haskell. Una soluzione che ho visto avvicinarsi a ciò che descrivi è il sistema CRUD in Yesod. Controlla il pacchetto Persistent su Hackage.

0

Se si dispone di un set limitato di tipi di file csv in fase di compilazione, è possibile scrivere qualcosa con il modello haskell. Ad esempio, se si ha avuto 2 tipi di file CSV: un file di log CSV e un file di opzioni CSV, e si aveva i seguenti due file di esempio:

//sample_logger.csv 
Date,Action,Succeeded 
20110808,print log,true 
20110929,save db,false 

// sample_options.csv 
Option,Value 
backgroundColor,green 
name,Fred 

Poi si potrebbe scrivere una funzione template Haskell che ha letto le prime righe di questi file e creato un tipo di dati OptionsCSVLine e LoggerCSVLine, con le funzioni readOptionsCVS :: FilePath -> IO [OptionsCSVLine] e readLoggerCSV :: FilePath -> IO [LoggerCSVLine]. Ad esempio:

-- CSVReader.hs 
makeCSVReader :: String -> FilePath -> Q [Dec] 
makeCSVReader dataTypeName sampleFilePath = sequence [makeDataType,makeReaderFunc] where 
    makeDataType = undefined -- todo 
    makeReaderFunc = undefined -- todo 


-- main.hs 
import CSVReader 
makeCVSReader "OptionsCSV" "sample_options.csv" 
makeCVSReader "LoggerCSV" "sample_logger.csv" 

main = do 
logLines <- readLoggerCSV "some_logger_file.csv" 
print $ map loggerLineDate logLines -- print all the dates in the log file 

Tuttavia, se si vuole far fronte a qualsiasi file CSV fornito in fase di esecuzione, allora non è possibile in alcun modo.

Problemi correlati