使用 csv-conduit 将 CSV 文件解析为自定义数据类型
Parse CSV file into custom data type with csv-conduit
我对如何将 csv-conduit 与自定义数据类型结合使用感到很困惑。我想获取一行股票数据,例如:
Date,Open,High,Low,Close,Volume,Adj Close
2017-02-10,2312.27002,2319.22998,2311.100098,2316.100098,3475020000,2316.100098
并将其解析为我在下面的 MWE 中声明的 StockInfo
类型。我从文档中了解到,我需要使 StockInfo
成为 FromNamedRecord
、ToNamedRecord
和 CSV ByteString
的实例。我相信我已经为前两个这样做了,但我不明白如何为 CSV ByteString
实现必要的方法。任何帮助将不胜感激。
MWE:
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
module Lib
( readStocks
) where
import Data.ByteString
import Data.Conduit
import Data.Conduit.Binary
import Data.Conduit.List as CL
import Data.CSV.Conduit
import Data.CSV.Conduit.Conversion
import Data.Text (Text)
import Data.Vector
import System.IO
readStocks :: FilePath -> IO (Vector StockInfo)
readStocks fp = readCSVFile defCSVSettings fp
data StockInfo = StockInfo
{ date :: !String
, open :: !Double
, high :: !Double
, low :: !Double
, close :: !Double
, volume :: !Integer
, adjClose :: !Double
}
instance FromNamedRecord StockInfo where
parseNamedRecord m =
StockInfo <$>
m .: "Date" <*>
m .: "Open" <*>
m .: "High" <*>
m .: "Low" <*>
m .: "Close" <*>
m .: "Volume" <*>
m .: "Adj Close"
instance ToNamedRecord StockInfo where
toNamedRecord (StockInfo date open high low close volume adjClose) =
namedRecord [ "Date" .= date
, "Open" .= open
, "High" .= high
, "Low" .= low
, "Close" .= close
, "Volume" .= volume
, "Adj Close" .= adjClose
]
instance CSV ByteString StockInfo where
-- rowToStr = undefined
-- intoCSV = undefined
-- fromCSV = undefined
这是我应该做的:
{-# LANGUAGE OverloadedStrings #-}
module Lib
( readStocks
) where
import Data.ByteString
import Data.Conduit
import Data.Conduit.Binary
import Data.CSV.Conduit
import Data.CSV.Conduit.Conversion
import Data.Text (Text)
import Data.Vector
import System.IO
readStocks :: FilePath -> IO (Vector (Named StockInfo))
readStocks fp = readCSVFile defCSVSettings fp
data StockInfo = StockInfo
{ date :: !String
, open :: !Double
, high :: !Double
, low :: !Double
, close :: !Double
, volume :: !Integer
, adjClose :: !Double
} deriving (Show, Eq, Read)
instance FromNamedRecord StockInfo where
parseNamedRecord m =
StockInfo <$>
m .: "Date" <*>
m .: "Open" <*>
m .: "High" <*>
m .: "Low" <*>
m .: "Close" <*>
m .: "Volume" <*>
m .: "Adj Close"
instance ToNamedRecord StockInfo where
toNamedRecord (StockInfo date open high low close volume adjClose) =
namedRecord [ "Date" .= date
, "Open" .= open
, "High" .= high
, "Low" .= low
, "Close" .= close
, "Volume" .= volume
, "Adj Close" .= adjClose
]
我对如何将 csv-conduit 与自定义数据类型结合使用感到很困惑。我想获取一行股票数据,例如:
Date,Open,High,Low,Close,Volume,Adj Close
2017-02-10,2312.27002,2319.22998,2311.100098,2316.100098,3475020000,2316.100098
并将其解析为我在下面的 MWE 中声明的 StockInfo
类型。我从文档中了解到,我需要使 StockInfo
成为 FromNamedRecord
、ToNamedRecord
和 CSV ByteString
的实例。我相信我已经为前两个这样做了,但我不明白如何为 CSV ByteString
实现必要的方法。任何帮助将不胜感激。
MWE:
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
module Lib
( readStocks
) where
import Data.ByteString
import Data.Conduit
import Data.Conduit.Binary
import Data.Conduit.List as CL
import Data.CSV.Conduit
import Data.CSV.Conduit.Conversion
import Data.Text (Text)
import Data.Vector
import System.IO
readStocks :: FilePath -> IO (Vector StockInfo)
readStocks fp = readCSVFile defCSVSettings fp
data StockInfo = StockInfo
{ date :: !String
, open :: !Double
, high :: !Double
, low :: !Double
, close :: !Double
, volume :: !Integer
, adjClose :: !Double
}
instance FromNamedRecord StockInfo where
parseNamedRecord m =
StockInfo <$>
m .: "Date" <*>
m .: "Open" <*>
m .: "High" <*>
m .: "Low" <*>
m .: "Close" <*>
m .: "Volume" <*>
m .: "Adj Close"
instance ToNamedRecord StockInfo where
toNamedRecord (StockInfo date open high low close volume adjClose) =
namedRecord [ "Date" .= date
, "Open" .= open
, "High" .= high
, "Low" .= low
, "Close" .= close
, "Volume" .= volume
, "Adj Close" .= adjClose
]
instance CSV ByteString StockInfo where
-- rowToStr = undefined
-- intoCSV = undefined
-- fromCSV = undefined
这是我应该做的:
{-# LANGUAGE OverloadedStrings #-}
module Lib
( readStocks
) where
import Data.ByteString
import Data.Conduit
import Data.Conduit.Binary
import Data.CSV.Conduit
import Data.CSV.Conduit.Conversion
import Data.Text (Text)
import Data.Vector
import System.IO
readStocks :: FilePath -> IO (Vector (Named StockInfo))
readStocks fp = readCSVFile defCSVSettings fp
data StockInfo = StockInfo
{ date :: !String
, open :: !Double
, high :: !Double
, low :: !Double
, close :: !Double
, volume :: !Integer
, adjClose :: !Double
} deriving (Show, Eq, Read)
instance FromNamedRecord StockInfo where
parseNamedRecord m =
StockInfo <$>
m .: "Date" <*>
m .: "Open" <*>
m .: "High" <*>
m .: "Low" <*>
m .: "Close" <*>
m .: "Volume" <*>
m .: "Adj Close"
instance ToNamedRecord StockInfo where
toNamedRecord (StockInfo date open high low close volume adjClose) =
namedRecord [ "Date" .= date
, "Open" .= open
, "High" .= high
, "Low" .= low
, "Close" .= close
, "Volume" .= volume
, "Adj Close" .= adjClose
]