2012-07-18 12 views
5

Sono stato suggerito csv-conduit come un buon pacchetto Haskell per lavorare con i file CSV. Voglio imparare come funziona, ma la documentazione è troppo concisa per un principiante programmatore Haskell.Haskell csv-conduit in GHCi

C'è un modo per me di capire come funziona per tentativi ed errori in GHCi?

Più in particolare, devo caricare i moduli e file da GHCi o dovrei scrivere un file HS semplice per caricarli e poi muovono intorno in modo interattivo?


ho citato CSV-condotto, ma io sono aperto ad usare qualsiasi pacchetto CSV. Ho solo bisogno di mettere le mie mani su uno e scherzare con esso, fino a quando mi sento a mio agio (proprio come farei in IDLE).

risposta

2

Hai provato Text.CSV? Potrebbe essere più appropriato se sei appena agli inizi con Haskell, in quanto è molto più semplice. Come per esplorare nuovi moduli, è sufficiente caricarlo in GHCi, non è necessario scrivere un file aggiuntivo.

5

Date un'occhiata al seguente funzione: readCSVFile :: :: (MonadResource m, CSV ByteString a) => CSVSettings -> FilePath -> m [a]

sua relativamente semplice da chiamare, come abbiamo solo bisogno di un CSVSettings, come defCSVSettings, e un FilePath (aka String), "file.csv" o qualcosa del genere.

Così, dopo la chiamata, otteniamo (MonadResource m, CSV ByteString a). Possiamo risolvere questo alla volta per capire un tipo appropriato per questo. Stiamo eseguendo IO in questa operazione, quindi per MonadResource m, m dovrebbe essere solo ResourceT IO, che risulta essere un'istanza di MonadBaseControl IO come richiesto da runResourceT. Questa è una cosa specifica di conduit.

Per il CSV ByteString a, dobbiamo trovare quali istanze di CSV. Per fare ciò, andare a http://hackage.haskell.org/packages/archive/csv-conduit/0.2.1.1/doc/html/Data-CSV-Conduit.html#t:CSV (dove la documentazione per il pacchetto è a mio parere in qualche modo odiosamente inserita nella classe di caratteri ...) e fare clic su Istanze per vedere quali istanze disponibili abbiamo del modulo CSV ByteString a. Le due opzioni sono CSV ByteString ByteString e CSV ByteString Text.

Di questi due, Text è preferibile perché gestisce unicode e CSV non conterrà probabilmente dati binari. ByteString è più o meno simile a [Word8] mentre Text è più simile a [Char] che è probabilmente quello che vuoi. Quindi, a dovrebbe essere Text (anche se ByteString funzionerà ancora).

Ciò significa che il risultato della chiamata di funzione è ResourceT IO [Row Text]. Non possiamo fare molto con questo, ma poiché ResourceT è un trasformatore monad, possiamo facilmente "far scattare" il layer di trasformazione monad con la funzione runResourceT. Così,

readFile :: FilePath -> IO [Row Text] 
readFile = runResourceT . readCSVFile defCSVSettings 

che è facilmente utilizzabile all'interno, diciamo, principale per arrivare al [Row Text] che è quindi possibile iterare su con un map o un fold per mettere le mani sulle singole righe.

Per eseguire questo genere di cose in GHCI è assolutamente necessario indicare il tipo. Il motivo è che l'istanza della classe result non dipende da nessuno dei parametri; pertanto, per qualsiasi serie di CSVSettings e FilePath, readCSVFile, è possibile restituire un numero qualsiasi di tipi diversi purché comesia un'istanza di MonadResource m e a sia un'istanza di CSV ByteString a. Pertanto, dobbiamo indicare esplicitamente a GHCi quale tipo desideri.

0

Funziona con l'ultima versione del pacchetto csv-conduit (versione 0.6.3). Nota la firma di readCsv senza la quale non potrei compilare.

{-# LANGUAGE OverloadedStrings #-} 

import Data.CSV.Conduit 
import Data.Text (Text) 
import qualified Data.Vector as V 
import qualified Data.ByteString as B 

csvset :: Char -> CSVSettings 
csvset c = CSVSettings {csvSep = c, csvQuoteChar = Just '"'} 

readCsv :: String -> Char -> IO (V.Vector (Row Text)) 
readCsv fp del = readCSVFile (csvset del) fp 

main = readCsv "C:\\mydir\\myfile.csv" ';' 
+0

con il pacchetto csv-condotto-0.6.6 firma readCsv dovrebbe essere 'readCsv :: String -> Char -> IO (V.Vector (Row B.ByteString))', sostituendo il testo con Fila Row B. ByteString – Janthelme