有人建议我将csv-conduit作为一个很好的 Haskell 包来处理 CSV 文件。我想了解它是如何工作的,但是对于新手 Haskell 程序员来说,文档太简洁了。
有没有办法让我通过 GHCi 中的反复试验来弄清楚它是如何工作的?
更具体地说,我应该从GHCi 加载模块和文件,还是应该编写一个简单的 HS 文件来加载它们,然后以交互方式移动?
我提到了 csv-conduit,但我愿意使用任何CSV 包。我只需要拿到一个并玩弄它,直到我感到自在(就像我在 IDLE 中所做的那样)。
有人建议我将csv-conduit作为一个很好的 Haskell 包来处理 CSV 文件。我想了解它是如何工作的,但是对于新手 Haskell 程序员来说,文档太简洁了。
有没有办法让我通过 GHCi 中的反复试验来弄清楚它是如何工作的?
更具体地说,我应该从GHCi 加载模块和文件,还是应该编写一个简单的 HS 文件来加载它们,然后以交互方式移动?
我提到了 csv-conduit,但我愿意使用任何CSV 包。我只需要拿到一个并玩弄它,直到我感到自在(就像我在 IDLE 中所做的那样)。
看看下面的函数:readCSVFile :: :: (MonadResource m, CSV ByteString a) => CSVSettings -> FilePath -> m [a]
调用起来相对简单,因为我们只需要一个CSVSettings,例如defCSVSettings,和一个FilePath(aka String),"file.csv"或其他东西。
因此,在调用之后,我们得到(MonadResource m, CSV ByteString a). 我们可以一次解决这个问题,以找出合适的类型。我们正在执行IO这个操作,所以 for MonadResource m,m应该只是ResourceT IO,它恰好是MonadBaseControl IOas 要求的一个实例runResourceT。这是一个conduit具体的事情。
对于CSV ByteString a,我们需要找到 的哪些实例CSV。为此,请访问http://hackage.haskell.org/packages/archive/csv-conduit/0.2.1.1/doc/html/Data-CSV-Conduit.html#t:CSV(其中包的文档在我看来有点令人讨厌的是所有都塞进了类型类...)然后单击 Instances 以查看我们有哪些可用的实例CSV ByteString a。两个选项是CSV ByteString ByteString和CSV ByteString Text。
在这两者中,Text更可取,因为它处理 unicode,而 CSV 不太可能包含二进制数据。ByteString或多或少类似于一段[Word8]时间Text更类似于[Char]这可能是您想要的。因此,a应该是Text(尽管ByteString仍然有效)。
这意味着函数调用的结果是ResourceT IO [Row Text]. 我们对此无能为力,但因为ResourceT它是一个 monad 转换器,我们可以使用 函数轻松“弹出” monad 转换层runResourceT。因此,
readFile :: FilePath -> IO [Row Text]
readFile = runResourceT . readCSVFile defCSVSettings
这很容易在 main 中使用,然后您可以使用 a或 a[Row Text]进行迭代以获取各个行。mapfold
要在 GHCI 中运行这类事情,您绝对必须特别指出类型。原因是结果类实例不依赖于任何参数;因此,对于任何一组CSVSettingsand FilePath,readCSVFile只要它们 asm是MonadResource m和a的一个实例,就可以返回任意数量的不同类型CSV ByteString a。因此,我们必须明确指出 GHCi 您想要哪种类型。
你试过Text.CSV吗?如果您刚开始使用 Haskell,它可能更合适,因为它更简单。至于探索新的模块,你可以把它加载到 GHCi 中,不需要编写额外的文件。
这适用于最新版本的 csv-conduit 包(版本 0.6.3)。请注意 readCsv 的签名,没有它我无法编译。
{-# 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" ';'