ファイル入出力をConduitに
メインモジュールがごちゃごちゃしてきたのでリファクタリング中。
ファイル入出力に関わる部分をConduitを用いたコードに直してみました。
最近Hotなので練習の意味も兼ねて。
以下のPDFを参照しました。
http://mew.org/~kazu/material/2012-conduit.pdf
とりあえず、Source型とSink型を$$演算子でくっつけて、runResourceTで走らせればいいと。
・ファイルから複数行に渡るデータを入力
Data.Conduit.Binary.sourceFile ::
MonadResource m =>
FilePath -> Source m Data.ByteString.Internal.ByteString
ファイルを指定してファイルの内容を供給するSourceを生成
Data.Conduit.Binary.lines ::
Monad m =>
Conduit
Data.ByteString.Internal.ByteString
m
Data.ByteString.Internal.ByteString
文字列データ(ByteString)を '\n' で区切る。このあとData.Conduit.Listの関数を適用すると、この一区切りが1単位として処理される。
例)
出力)
>test0
DATA: data0
data1
data2
data3
>test1
DATA: data0DATA: data1DATA: data2DATA: data3
Data.Conduit.List.map :: Monad m => (a -> b) -> Conduit a m b
map関数のConduit版。Sourceから得られるデータに対し第一引数の関数を適用する。
Data.Conduit.List.take :: Monad m => Int -> Sink a m [a]
take関数のConduit版、指定した個数だけ値を消費するSinkを生成。
で、上の関数を使うとこんなふうになります。アクセストークン及びユーザ情報を取り出す関数。
・Stringのリストを複数行にファイル出力
Data.Conduit.List.sourceList :: Monad m => [a] -> Source m a
リストの値を供給するSourceを生成
Data.Conduit.Binary.sinkFile ::
MonadResource m =>
FilePath -> Sink Data.ByteString.Internal.ByteString m ()
流れてきたデータをファイルへ書き込むSinkを生成。
さっきのファイル出力と逆のことをやればいい訳ですが、Data.List.unlinesにあたるConduitがなかったので、代わりにmapで文字列末尾に改行を付け足しました。
unlinesに当たるConduitを書こうとも思ったんですが、書けませんでした……