您可以使用pipes-binary
和来做到这一点pipes-bytestring
。这是一个帮助您的功能:
import Control.Monad (void)
import Data.Binary
import Pipes
import Pipes.Binary (decodeMany)
import Pipes.ByteString (fromHandle)
import qualified Pipes.Prelude as P
import System.IO
decodeHandle :: (Binary a) => Handle -> Producer a IO ()
decodeHandle handle = void $ decodeMany (fromHandle handle) >-> P.map snd
void
and之所以存在,map snd
是因为decodeMany
实际上返回了更多信息(如字节偏移和解析错误)。如果您确实想要该信息,则只需删除它们即可。
这是一个如何使用的示例,使用我拼凑decodeHandle
的快速骨架:Trade
data Trade = Trade
instance Binary Trade where
get = return Trade
put _ = return ()
instance Show Trade where show _ = "Trade"
main = withFile "inFile.txt" ReadMode $ \handle -> runEffect $
for (decodeHandle handle) $ \trade -> do
lift $ print (trade :: Trade)
-- do more with the parsed trade
您可以使用for
循环解码的交易并处理它们,或者如果您愿意,您可以使用管道组合:
main = withFile "inFile.txt" ReadMode $ \handle -> runEffect $
decodeHandle handle >-> P.print
这将是懒惰的,并且只解码您实际需要的交易数量。因此,如果您take
在解码器和打印机之间插入 a,它只会读取处理请求的交易数量所需的输入:
main = withFile "inFile.txt" ReadMode $ \handle -> runEffect $
for (decodeHandle handle >-> P.take 4) $ \trade -> do
... -- This will only process the first 4 trades
-- or using purely pipe composition:
main = withFile "inFile.txt" ReadMode $ \handle -> runEffect $
decodeHandle handle >-> P.take 4 >-> P.print