【问题标题】:Haskell csv-conduit in GHCiGHCi 中的 Haskell csv-conduit
【发布时间】:2012-07-18 17:42:47
【问题描述】:

有人建议我将 csv-conduit 作为一个很好的 Haskell 包来处理 CSV 文件。我想了解它是如何工作的,但是对于新手 Haskell 程序员来说,文档太简洁了。

有没有办法让我通过 GHCi 中的反复试验来弄清楚它是如何工作的?

更具体地说,我应该 GHCi 加载模块和文件,还是应该编写一个简单的 HS 文件来加载它们并然后以交互方式移动?


我提到了 csv-conduit,但我愿意使用 any CSV 包。我只需要拿到一个并玩弄它,直到我感到自在(就像我在 IDLE 中所做的那样)。

【问题讨论】:

    标签: haskell csv


    【解决方案1】:

    看看下面的函数:readCSVFile :: :: (MonadResource m, CSV ByteString a) => CSVSettings -> FilePath -> m [a]

    调用起来相对简单,因为我们只需要一个CSVSettings,例如defCSVSettings,和一个FilePath(又名String),"file.csv" 或其他东西。

    因此,在调用之后,我们得到(MonadResource m, CSV ByteString a)。我们可以一次解决这个问题,以找出合适的类型。我们在这个操作中执行IO,所以对于MonadResource mm 应该只是ResourceT IO,这恰好是MonadBaseControl IO 的一个实例,正如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(在我看来,该包的文档有点令人讨厌地全部塞进类型类中......)并单击实例以查看我们拥有CSV ByteString a 形式的可用实例。这两个选项是CSV ByteString ByteStringCSV ByteString Text

    在这两个中,Text 更可取,因为它处理 unicode,而 CSV 不太可能包含二进制数据。 ByteString 或多或少类似于[Word8],而Text 更类似于[Char],这可能是您想要的。因此,a 应该是 Text(尽管 ByteString 仍然可以使用)。

    这意味着函数调用的结果是ResourceT IO [Row Text]。我们对此无能为力,但因为ResourceT 是一个monad 转换器,我们可以使用runResourceT 函数轻松“弹出” monad 转换层。因此,

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

    这很容易在 main 中使用以获取 [Row Text],然后您可以使用 mapfold 进行迭代以获取各个行。

    要在 GHCI 中运行这类事情,您绝对必须明确指出类型。原因是结果类实例不依赖于任何参数;因此,对于CSVSettingsFilePath 的任何集合,readCSVFile 可以返回任意数量的不同类型,只要它们mMonadResource m 的一个实例并且aCSV ByteString a 的一个实例.因此,我们必须向 GHCi 明确指出您想要哪种类型。

    【讨论】:

      【解决方案2】:

      你试过Text.CSV吗?如果您刚开始使用 Haskell,它可能更合适,因为它更简单。 至于探索新模块,直接加载到 GHCi 即可,无需额外编写文件。

      【讨论】:

        【解决方案3】:

        这适用于最新版本的 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" ';'
        

        【讨论】:

        • 带有包 csv-conduit-0.6.6 的 readCsv 签名应为 readCsv :: String -> Char -> IO (V.Vector (Row B.ByteString)),将 Row Text 替换为 Row B.ByteString
        猜你喜欢
        • 1970-01-01
        • 2011-12-18
        • 1970-01-01
        • 2017-04-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-22
        相关资源
        最近更新 更多