2

解析して処理する必要がある CSV ダンプ ファイルでいっぱいのディレクトリがあります。各ファイル名には、抽出方法を知っているタイムスタンプが含まれています。次に、ダンプからすべての行を処理する必要がありますが、各行について、そのファイルのタイムスタンプが何であったかを知る必要があります。タイムスタンプを個別に取得でき、ファイルからすべての行を個別に取得できます ( Haskell で `cat` を実装するにはどうすればよいですか? に従ってください) が、それらを結合する方法が見つかりません。何か案は?

{-# LANGUAGE OverloadedStrings #-}
module Main (main) where

import Control.Monad.Trans.Resource (MonadResource, runResourceT)
import Data.Conduit (($=), ($$))
import qualified Data.Conduit as C (Conduit, awaitForever)
import qualified Data.Conduit.Binary as C (sinkHandle, sourceFile)
import qualified Data.Conduit.Combinators as C (map, sourceDirectory, unlines)
import qualified Data.Conduit.Text as C (decode, encode, utf8)
import Data.Text (Text, pack)
import Data.Time (LocalTime)
import Filesystem.Path.CurrentOS (FilePath)
import System.IO (stdout)
import Prelude hiding (FilePath)

decodeFilePath :: FilePath -> Text
decodeFilePath = undefined

decodeFilePathToString :: FilePath -> String
decodeFilePathToString = undefined

extractTimestamp :: Text -> LocalTime
extractTimestamp = undefined

readFileConduit :: MonadResource m => C.Conduit FilePath m Text
readFileConduit =
  C.awaitForever (\fp -> C.sourceFile (decodeFilePathToString fp) $= C.decode C.utf8)

readFileWithTimestampConduit :: MonadResource m => C.Conduit FilePath m (LocalTime, Text)
readFileWithTImestampConduit = ???

main :: IO ()
main = do
  runResourceT $
    C.sourceDirectory "data/dumps" $=
    C.map (pack . show . extractTimestamp . decodeFilePath) $=
    C.unlines $=
    C.encode C.utf8 $$
    C.sinkHandle stdout
  runResourceT $
    C.sourceDirectory "data/dumps" $=
    readFileConduit $=
    C.unlines $=
    C.encode C.utf8 $$
    C.sinkHandle stdout

編集: acomar のおかげで、私はこの解決策を持っています:

readFileWithTimestampConduit :: MonadResource m => C.Conduit FilePath m (LocalTime, Text)
readFileWithTimestampConduit =
  C.awaitForever (\fp ->
    C.sourceFile (decodeFilePathToString fp) $=
    C.decode C.utf8 $=
    C.linesUnbounded $=
    C.map (\t -> (extractTimestamp $ decodeFilePath fp, t)))

ファイルからの行を含む別のコンジットで、タイムスタンプを含む 1 つのコンジットを圧縮するアプローチを考えられる人はいますか? それが、この質問をする前に私がやろうとしていたことです。

4

1 に答える 1

1

更新された質問への回答:

コンジットの設定方法が原因で、これはうまく機能しません。コンジットの着信型は、単一の値を受け取るように固定されていることに注意してください。

MonadResource m => C.Conduit i m o

複数の入力を取りたい場合は、それらをペアとしてリクエストする必要があります

MonadResource m => C.Conduit (i1, i2) m o

しかし、そのコンジットに入力を与えるために、既に既存のソリューションを作成しています!

一方、Conduit を Arrow にする方法があれば、必要な(***)機能を正確に実行する関数を使用して、それほど困難なくこれを行うことができます。つまり、2 つの入力矢印を取り、それらを組み合わせて、に作用する矢印を生成します。二つ。私の理解では、コンジットをアローに変える良い方法はありません。ただし、( と を使用して)にダウングレードreadFileConduitすると、 IO モナドの内部で構成できます。readFileHandlehGetContentsextractTimeStampreadFile

do let timestamp = extractTimeStamp <..args..>
   contents <- readFile <..args..>
   return (timestamp, contents)

次に、その関数を単純な でコンジットに持ち上げることができますlift

于 2014-04-25T23:00:42.767 に答える