使用csv管道从csv文件读取第一行

使用csv管道从csv文件读取第一行,csv,haskell,haskell-pipes,Csv,Haskell,Haskell Pipes,我正在用管道csv库读取csv文件。我想读第一行,以后再读其余的。不幸的是,Pipes.Prelude.head函数返回后。管道不知怎么被堵住了。是否有一种方法可以先读取csv的头部,然后再读取其余部分 import qualified Data.Vector as V import Pipes import qualified Pipes.Prelude as P import qualified System.IO as IO import qualified Pipes.ByteStrin

我正在用管道csv库读取csv文件。我想读第一行,以后再读其余的。不幸的是,Pipes.Prelude.head函数返回后。管道不知怎么被堵住了。是否有一种方法可以先读取csv的头部,然后再读取其余部分

import qualified Data.Vector as V
import Pipes
import qualified Pipes.Prelude as P
import qualified System.IO as IO
import qualified Pipes.ByteString as PB
import qualified Data.Text as Text
import qualified Pipes.Csv as PCsv
import Control.Monad (forever)

showPipe :: Proxy () (Either String (V.Vector Text.Text)) () String IO b
showPipe = forever $ do
    x::(Either String (V.Vector Text.Text)) <- await
    yield $ show x


main :: IO ()
main = do
  IO.withFile "./test.csv"
              IO.ReadMode
              (\handle -> do
                  let producer = (PCsv.decode PCsv.NoHeader (PB.fromHandle handle))
                  headers <- P.head producer
                  putStrLn "Header"
                  putStrLn $ show headers
                  putStrLn $ "Rows"
                  runEffect ( producer>->
                              (showPipe) >->
                              P.stdoutLn)
               )

Pipes.Csv
有处理标题的材料,但我认为这个问题实际上是在寻找更复杂的
管道用法。等待
或者
管道。下一步
。第一个
下一个

>>> :t Pipes.next 
Pipes.next :: Monad m => Producer a m r -> m (Either r (a, Producer a m r))
next
是检查生产商的基本方法。这有点像列表上的模式匹配。有了一个列表,两种可能性是
[]
x:xs
——这里是
左()
右(标题、行)
。后一双就是你要找的。当然,需要一个动作(在
IO
中)来控制它:

main :: IO ()
main = do
  handle <- IO.openFile  "./test.csv" IO.ReadMode
  let producer :: Producer (V.Vector Text.Text) IO ()
      producer = PCsv.decode PCsv.NoHeader (PB.fromHandle handle)  >-> P.concat
  e <- next producer
  case e of
    Left () -> putStrLn "No lines!"
    Right (headers, rows) -> do
      putStrLn "Header"
      print headers
      putStrLn $ "Rows"
      runEffect ( rows >-> P.print)
  IO.hClose handle
不同之处在于,如果
producer
为空,我将无法声明它,就像我对
无行所做的那样在上一个程序中


请注意,
showPipe
可以定义为
p.map show
,或者简单地定义为
p.show
(但使用您添加的专用类型)。

p.接下来是针对我的案例的完美解决方案。同样感谢您展示地图版的showPipe。用P.concat删除这两个选项也是一个很好的技巧。
main :: IO ()
main = do
  handle <- IO.openFile  "./test.csv" IO.ReadMode
  let producer :: Producer (V.Vector Text.Text) IO ()
      producer = PCsv.decode PCsv.NoHeader (PB.fromHandle handle)  >-> P.concat
  e <- next producer
  case e of
    Left () -> putStrLn "No lines!"
    Right (headers, rows) -> do
      putStrLn "Header"
      print headers
      putStrLn $ "Rows"
      runEffect ( rows >-> P.print)
  IO.hClose handle
main :: IO ()
main = do
  handle <- IO.openFile  "./grades.csv" IO.ReadMode
  let producer :: Producer (V.Vector Text.Text) IO ()
      producer = PCsv.decode PCsv.NoHeader (PB.fromHandle handle)  >-> P.concat
      handleHeader :: Pipe (V.Vector Text.Text) (V.Vector Text.Text) IO ()
      handleHeader = do
        headers <- await  -- intercept first value
        liftIO $ do       -- use it for IO
          putStrLn "Header"
          print headers
          putStrLn $ "Rows"
        cat               -- pass along all later values
  runEffect (producer >-> handleHeader >-> P.print)
  IO.hClose handle