简体   繁体   English

Haskell类型与CSV解析不匹配

[英]Haskell type mismatch with csv parsing

I'm trying to parse a csv file where I want to ignore the first line and the last line, as in: 我正在尝试解析一个csv文件,其中我想忽略第一行和最后一行,如下所示:

Someheader
foo, 1000,
bah, 2000,
somefooter

I wrote some Haskell using the cassava library: 我使用木薯库编写了一些Haskell:

{-# LANGUAGE OverloadedStrings #-}

import Control.Applicative
import qualified Data.ByteString.Lazy as BL
import Data.Csv
import qualified Data.Vector as V
import Control.Monad (mzero)

data Demand = Demand
    { name     :: !String
    , amount   :: !Int
    } deriving Show

instance FromRecord Demand where
    parseRecord r 
         | length == 2 = Demand <$> r .! 0
                                <*> r .! 1
         | otherwise = mzero

main :: IO ()
main = do
    csvData <- BL.readFile "demand.csv"
    case decode HasHeader csvData of
        Left err -> putStrLn err
        Right (_, v) -> V.forM_ v $ \ p ->
            putStrLn $ (name p) ++ " amount " ++ show (amount p)

When I run this get a type mismatch, that I can't figure out: 当我运行此命令时,我发现类型不匹配:

parser.hs:34:15: error:
    • Couldn't match expected type ‘V.Vector a2’
                  with actual type ‘(a1, V.Vector Demand)’
    • In the pattern: (_, v)
      In the pattern: Right (_, v)

My guess is that I haven't unpacked the Vector in the record correctly? 我的猜测是我没有正确地将Vector中的Vector解压缩吗? Any help, gratefully received. 任何帮助,感激不尽。

decode has the type FromRecord a => HasHeader -> ByteString-> Either String (Vector a) based on the documentation for cassava. 根据木薯的文档decode的类型为FromRecord a => HasHeader -> ByteString-> Either String (Vector a)
So the correct pattern would be Right v instead of Right (_, v) . 因此正确的模式应该是Right v而不是Right (_, v)

Another problem in the code, is that length is a function, and you didn't apply it to anything, in the guard | length == 2 = ... 在代码中的另一个问题是, length是一个函数,而你没有把它应用到任何东西,在中后卫| length == 2 = ... | length == 2 = ... . | length == 2 = ... I believe the correct code should instead be | length r == 2 = ... 我相信正确的代码应该改为| length r == 2 = ... | length r == 2 = ...

Here's the complete code after those changes: 这些更改后的完整代码如下:

{-# LANGUAGE OverloadedStrings #-}

import Control.Applicative
import qualified Data.ByteString.Lazy as BL
import Data.Csv
import qualified Data.Vector as V
import Control.Monad (mzero)

data Demand = Demand
    { name     :: !String
    , amount   :: !Int
    } deriving Show

instance FromRecord Demand where
    parseRecord r 
         | length r == 2 = Demand <$> r .! 0
                                <*> r .! 1
         | otherwise = mzero

main :: IO ()
main = do
    csvData <- BL.readFile "demand.csv"
    case decode HasHeader csvData of
        Left err -> putStrLn err
        Right v -> V.forM_ v $ \ p ->
            putStrLn $ (name p) ++ " amount " ++ show (amount p)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM